]> git.donarmstrong.com Git - lib.git/blob - emacs_el/mode-compile.el
fix missing ) for org-mode
[lib.git] / emacs_el / mode-compile.el
1 ;;; mode-compile.el ---  Smart command for compiling files
2 ;;                       according to major-mode.
3 ;;
4 ;;   Copyright (c) 1994 - 2003 heddy Boubaker C.E.N.A.
5 ;;
6 ;;   Author: Heddy Boubaker <heddy.Boubaker@cena.fr>
7 ;;   Maintainer: Heddy Boubaker <heddy.Boubaker@cena.fr>
8 ;;   Created: June 1994
9 ;;   Last modified: 2003/04/01 13:52:47
10 ;;   Version: 2.28
11 ;;   Keywords: compile, compilation, modes, languages
12 ;;   Tested for:
13 ;;     XEmacs (Lucid GNU Emacs) >= 19.10
14 ;;     Must work with FSF GNU Emacs > 19.31 ;-)
15 ;;     Do not work anymore for Emacses <= 18
16 ;;   Ftp access:
17 ;;    archive.cis.ohio-state.edu:pub/gnu/emacs/elisp-archive/misc/mode-compile.el.Z
18 ;;   WWW access:
19 ;;    <URL http://www.tls.cena.fr/~boubaker/Emacs/>
20 ;;
21 ;; LCD Archive Entry:
22 ;; mode-compile|Heddy Boubaker|boubaker@cena.fr|
23 ;; Smart command for compiling files according to major-mode and more.|
24 ;; 2003/04/01 13:52:47|2.28|~/misc/mode-compile.el.Z|
25 ;;
26 ;;; This file is NOT part of GNU Emacs but the same permissions apply.
27 ;;
28 ;; GNU Emacs is free software; you can redistribute  it and/or modify it under
29 ;; the terms  of  the GNU General   Public License as   published  by the Free
30 ;; Software Foundation;    either version 2,   or (at  your option)  any later
31 ;; version.
32 ;;
33 ;; GNU Emacs  is distributed in  the hope that it will  be useful, but WITHOUT
34 ;; ANY  WARRANTY; without  even the  implied   warranty of MERCHANTABILITY  or
35 ;; FITNESS  FOR A PARTICULAR PURPOSE.  See  the GNU General Public License for
36 ;; more details.
37 ;;
38 ;; You  should have received a  copy of the GNU  General  Public License along
39 ;; with GNU Emacs; see the  file COPYING.  If  not, write to the Free Software
40 ;; Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
41 ;;
42 ;; @ Purpose:
43 ;; ==========
44 ;;
45 ;;  Provide `mode-compile' function as a replacement  for the use of `compile'
46 ;;  command which  is  very dumb  for  creating it's  compilation command (use
47 ;;  "make  -k" by default).  `mode-compile'  is  a layer  above `compile'; Its
48 ;;  purpose is mainly   to  build a  smart  compile-command for  `compile'  to
49 ;;  execute  it. This   compile-command is   built   according  to number   of
50 ;;  parameters:
51 ;;   - the major-mode.
52 ;;   - presence or not of a makefile in current directory.
53 ;;   - the buffer-file-name and extension.
54 ;;   - what is in the current buffer (`main' function,"#!/path/shell", ...).
55 ;;   - and more ... (see Commentary section below).
56 ;;  Most  of  these  parameters  are  higly customizable  throught Emacs  Lisp
57 ;;  variables  (to be  set  in your  .emacs  or  through Customization  menu).
58 ;;  Running  mode-compile after   an  universal-argument (C-u)  allows  remote
59 ;;  compilations, user is  prompted  for a host name   to run the  compilation
60 ;;  command on.   Another  function  provided  is  `mode-compile-kill'   which
61 ;;  terminate a running compilation session launched by `mode-compile'.
62 ;;
63 ;; @ Installation:
64 ;; ===============
65 ;;
66 ;;   Byte compile this file (*) somewhere in your `load-path' and add in
67 ;;  your .emacs:
68 ;;  (autoload 'mode-compile "mode-compile"
69 ;;   "Command to compile current buffer file based on the major mode" t)
70 ;;  (global-set-key "\C-cc" 'mode-compile)
71 ;;  (autoload 'mode-compile-kill "mode-compile"
72 ;;   "Command to kill a compilation launched by `mode-compile'" t)
73 ;;  (global-set-key "\C-ck" 'mode-compile-kill)
74 ;;
75 ;;  By  default mode-compile is  very verbose  and  waits a  few seconds (1 by
76 ;;  default) after  each message for   the user to have  time  to read it. You
77 ;;  could      set           variables      `mode-compile-expert-p'        and
78 ;;  `mode-compile-reading-time'   to  change  this    behaviour.  On X-Windows
79 ;;  systems  setting the variable  `mode-compile-other-frame-p'  will create a
80 ;;  new frame and launch the compilation command in it.
81 ;;
82 ;;  (*) Don't take care of messages:
83 ;;        ** reference to free variable efs-remote-shell-file-name
84 ;;      This is perfectly normal ;-}. But if you know a way to avoid it let me
85 ;;      know.
86 ;;
87 ;; @ Bug Reports:
88 ;; ==============
89 ;;
90 ;;   To   report a  bug  please  use function `mode-compile-submit-bug-report'
91 ;;   Please note that this bug-report facility uses Barry Warsaw's reporter.el
92 ;;   which is part of GNU Emacs v19 and bundled with many  other packages.  If
93 ;;   needed, you can obtain a copy of reporter.el at the elisp-archive.
94 ;;
95 ;; @ Documentation:
96 ;; ================
97 ;;
98 ;;  This section will explain how the `compile-command' are built according to
99 ;;  the `major-mode' and how to  customize it.  The major modes `mode-compile'
100 ;;  currently known are:
101 ;;   - c-mode, c++-mode, makefile-mode, dired-mode, ada-mode, emacs-lisp-mode,
102 ;;     lisp-interaction-mode, sh-mode, csh-mode, fundamental-mode,  text-mode,
103 ;;     indented-text-mode     compilation-mode,  fortran-mode,    c?perl-mode,
104 ;;     zsh-mode java-mode, tcl-mode, python-mode
105 ;;  For other modes a default behaviour is provided.
106 ;;
107 ;;  When    running    `mode-compile'  or     `mode-compile-kill'   the  hooks
108 ;;  `mode-compile-(before|after)-(compile|kill)-hook'  are   executed.     The
109 ;;  current   buffer   could   be      automaticaly    saved    if    variable
110 ;;  `mode-compile-always-save-buffer-p' is  set  to   `t'.  ALL  the  modified
111 ;;  buffers could  be automaticaly saved if variable `mode-compile-save-all-p'
112 ;;  is set to `t'.
113 ;;
114 ;; @@ fundamental-mode, text-mode, indented-text-mode & UNKNOWN MODES:
115 ;;    *** THIS IS TOO THE DEFAULT BEHAVIOR FOR UNKNOWN MODES ***
116 ;;    Try to guess what the file is by:
117 ;;   - 1st looking at it's name and extension (see variable
118 ;;     `mode-compile-filename-regexp-alist').
119 ;;   - 2nd looking at string "#!/path/shell" at first line to extract shell
120 ;;     to run the script with (see variable `mode-compile-shell-alist').
121 ;;   - 3rd looking at a makefile in current directory.
122 ;;   - then calling `compile' with the last compile command which is
123 ;;     asked to be edited by user ...
124 ;;   The `kill-compile' command is then bound dynamically (buffer-local).
125 ;;
126 ;; @@ compilation-mode:
127 ;;    Call `compile' with the last compile command.
128 ;;
129 ;; @@ makefile-mode:
130 ;;    The makefile is run with make throught `compile' (user is prompted
131 ;;   for        the        rule         to      run,      see         variable
132 ;;   `mode-compile-prefered-default-makerule'  to  see how  a   default choice
133 ;;   could be selected).
134 ;;
135 ;; @@ emacs-lisp-mode, lisp-interaction-mode:
136 ;;    If the buffer is a .el file byte-compile it to produce a .elc file,
137 ;;   else  just  byte-compile  the   buffer  (this   don't  use  `compile' but
138 ;;   `byte-compile').
139 ;;
140 ;; @@ dired-mode:
141 ;;   Find a makefile   in   the directory and  run    make with  it   (like in
142 ;;   makefile-mode),  else try  to byte-recompile  all .el   files olders than
143 ;;   their associated  .elc  files (unlike  `byte-recompile-directory' this is
144 ;;   not  recursive),  finally if  no  .el  files  are present ask compilation
145 ;;   command to  user by  calling  `default-compile'.  To  find  a  makefile a
146 ;;   regexp is provided which name is `mode-compile-makefile-regexp'.
147 ;;
148 ;; @@ sh-mode, csh-mode, zsh-mode:
149 ;;    Run "[cz]?sh" with debugging arguments as specified in
150 ;;   `[cz]?sh-dbg-flags' on the currently edited file.
151 ;;
152 ;; @@ c?perl-mode:
153 ;;    Run  file with "perl   -w"  (can step   throught errors  with  compile's
154 ;;    `next-error' command).
155 ;;
156 ;; @@ tcl-mode:
157 ;;    Run     file  with "wish"  (can     step  throught errors with compile's
158 ;;    `next-error' command).
159 ;;
160 ;; @@ c-mode, c++-mode:
161 ;;   First it try to see if there is a makefile in the directory, makefiles to
162 ;;   look for are  specified  by the variable  `mode-compile-makefile-regexp'.
163 ;;   If yes two cases could happen: there  is only one  makefile so use it, or
164 ;;   there is more  than one (sometimes when  you need to  write portable soft
165 ;;   you  could have  some makefiles by  system:  SunOs.make, HP.make ...), in
166 ;;   that case prompt to  user for choice  (with smart completion).   Once the
167 ;;   makefile has been selected  it extract the rules from  it and ask to user
168 ;;   to   choose  a   rule  to  make  (with  smart  completion,  see  variable
169 ;;   `mode-compile-prefered- default-makerule'  to  see  how  a default choice
170 ;;   could be selected).
171 ;;
172 ;;   There are some cases where no makefiles are  presents (YES I KNOW this is
173 ;;   bad  practice but you  sometimes have no  needs  to write a Makefile). In
174 ;;   that case the  function try  to build  the most intelligent   compilation
175 ;;   command by using the favourite  user C/C++ compiler: value of environment
176 ;;   variable "CC"  or "CXX"  or  first found,   in  the PATH,   of  compilers
177 ;;   specified in variable  `cc-compilers-list' or `c++-compilers-list'.  Then
178 ;;   it look for the  varenv "CFLAGS" of  "CXXFLAGS" to append to the compiler
179 ;;   command,        find            the     file         to          compile:
180 ;;   <name-of-the-file-to-compiled>.(c|cc|C|cpp)  (see    *)   and   ask   for
181 ;;   confirmation.  If  you  really trust mode-compile   will build  the right
182 ;;   command  and  want to  bypass confirmation  you  could  set the  variable
183 ;;   `mode-compile-never-edit-command-p' to t.
184 ;;
185 ;;   (*) How to find <name-of-the-file-to-compiled>:
186 ;;    In both case the command try to guess which file has to be compiled:
187 ;;   It's a trivial choice when current buffer file is a
188 ;;   .(c|C|cc|cpp... -any file with extension specified in
189 ;;   `cc-source-file-ext-list' or `c++-source-file-ext-list') file but
190 ;;   when it's a .(h|H|hh) file what to do?  The variable
191 ;;   `cc-companion-file-regexp' or `c++-companion-file-regexp' specify
192 ;;   how to find a .(c|C|cc|cpp...) file from a .(h|H|hh...); This is
193 ;;   done by appending .(c|C|cc|cpp) to
194 ;;   <filename-without-matching-regexp>.  In c-mode with default value
195 ;;   it produce:
196 ;;      file.h, file_[Pp].h -> file.c
197 ;;      I sometimes use files _p.h to indicate that the file is a private header
198 ;;      file for a .c file.
199 ;;   In c++-mode with default value it produce:
200 ;;      file.hh, file_[Pp].hh -> file.cc
201 ;;      I sometimes use files _p.cc to indicate that the file is a private header
202 ;;      file for a .cc file.
203 ;;   The output of compilation will be a
204 ;;   <name-of-the-file-to-compiled>.o file if no `main' function is
205 ;;   found inside or a <name-of-the-file-to-compiled> EXECUTABLE file
206 ;;   if `main' function found.
207 ;;
208 ;; @@ ada-mode:
209 ;;   Same  as c/c++-mode but  run Ada compiler on the  Ada file.  There are no
210 ;;   companion file and no way to find a main function in Ada.
211 ;;
212 ;; @@ fortran-mode:
213 ;;    Same as c-mode but run Fortran compiler on .[Ff](or)? files.
214 ;;
215 ;; @@ java-mode:
216 ;;    Same as c-mode but call "javac" without the -o option on .java files
217 ;;
218 ;; @@  python-mode:
219 ;;    Run file with "python" (can step throught errors with compile's
220 ;;    `next-error' command).
221 ;;
222 ;; @@  message-mode:
223 ;;    Run `message-send'.
224 ;;
225 ;; @ WhatsNew:
226 ;; ===========
227 ;;
228 ;;  Support for cperl-mode
229 ;;  Require cl 
230 ;;
231 ;; @ Contributors/Helpers:
232 ;; =======================
233 ;;
234 ;;   Adrian Aichner <aichner@ecf.teradyne.com>
235 ;;   "William A. Perkins" <wa_perkins@pnl.gov>
236 ;;   Bin Mu <mubin@DerivaTech.COM>
237 ;;   Gael MARZIOU <Gael_Marziou@grenoble.hp.com>
238 ;;   Christian Motschke <motschke@prosun.first.gmd.de>
239 ;;   boris <boris@cs.rochester.edu>
240 ;;   Edward Hartnett <ejh@larry.gsfc.nasa.gov>.
241 ;;   Hartmut MANZ <manz@intes-stuttgart.de>.
242 ;;   Henry Guillaume <henryg@tusc.com.au>.
243 ;;   Ian Young <imy@wcl-rs.bham.ac.uk>
244 ;;   Ilya Zakharevich <ilya@math.ohio-state.edu>.
245 ;;   Kevin Broadey <KevinB@bartley.demon.co.uk>.
246 ;;   Lawrence R. Dodd <dodd@roebling.poly.edu>.
247 ;;   Martin Jost <asictest@ztivax.zfe.siemens.de>.
248 ;;   Michael Welsh Duggan <md5i+@andrew.cmu.edu>.
249 ;;   Rolf EBERT <rolf@gundog.lbl.gov>.
250 ;;   Scott Hofmann <scotth@visix.com>.
251 ;;   Stefan Schoef <Stefan.Schoef@arbi.informatik.uni-oldenburg.de>.
252 ;;   John W. Harwell <ccjohnh@showme.missouri.edu> - JWH.
253 ;;
254 ;; @ ToDo:
255 ;; =======
256 ;;
257 ;;   Extending this to some others programming languages (modes).
258 ;;   Writting an Info documentation.
259 ;;   Contributors are greatly accepted (send me diffs and don't forget to
260 ;;   update documentation and all comments too please).
261 ;;   Maybe Using ange-ftp parse .netrc utilities for remote host and
262 ;;   user infos.
263 ;;
264 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
265 \f
266
267 ;; @ Requirements ;;;
268
269 ;; mode-compile is not a replacement for compile
270 ;; it is just a layer above it.
271 (require 'compile)
272 ;;; For Emacs-Lisp files compilations
273 (require 'byte-compile "bytecomp")
274 ;;; For easy macros
275 (require 'backquote)
276 (require 'cl)
277 (load-library "cl-macs")
278 ;; Pretty print elisp
279 (require 'pp)
280 ;;; Setting obsolete vars
281 (eval-and-compile
282   (condition-case ()
283       (require 'obsolete)
284     (error nil))
285   (if (and (featurep 'obsolete) (fboundp 'define-obsolete-variable-alias))
286       nil ;; We've got what we needed
287     (defmacro define-obsolete-variable-alias (old new)
288       (` (progn (defalias (, old) (, new))
289                 (put (, old) 'byte-obsolete-variable (, new)))
290          ))))
291 ;;; For using custom - stolen from w3-cus.el -
292 (eval-and-compile
293   (condition-case ()
294       (require 'custom)
295     (error nil))
296   (if (and (featurep 'custom) (fboundp 'custom-declare-variable))
297       nil ;; We've got what we needed
298     ;; We have the old custom-library, hack around it!
299     (defmacro defgroup (&rest args)
300       nil)
301     (defmacro defcustom (var value doc &rest args)
302       (` (defvar (, var) (, value) (, doc))))))
303
304 ;; Custom groups
305 (defgroup compilation nil
306   "Compilations from within Emacs variables."
307   :link '(url-link :tag "Author's Emacs Page"
308                    "http://www.tls.cena.fr/~boubaker/Emacs/")
309   :group 'tools
310   :group 'development)
311 (defgroup compilation-lang nil
312   "Language specific compilation options."
313   :group 'languages
314   :group 'compilation)
315 (defgroup compilation-script nil
316   "Scripts compilation options."
317   :group 'compilation)
318 (defgroup compilation-elisp nil
319   "Emacs developpement compilation options."
320   :group 'lisp
321   :group 'compilation)
322
323 ;; @ User variables ;;;
324 ;; @@ Common variables to mode-compile for all modes ;;;
325
326 (defcustom mode-compile-modes-alist
327   '((c-mode                . (cc-compile        kill-compilation))
328     (java-mode             . (java-compile      kill-compilation))
329     (c++-mode              . (c++-compile       kill-compilation))
330     (ada-mode              . (ada-compile       kill-compilation))
331     (fortran-mode          . (f77-compile       kill-compilation))
332     (dired-mode            . (dired-compile     kill-compilation))
333     (emacs-lisp-mode       . (elisp-compile     keyboard-quit)) ; I'm SURE IT'S NOT the best way
334     (lisp-interaction-mode . (elisp-compile     keyboard-quit)) ; to kill a byte-compilation.
335     (makefile-mode         . (makefile-compile  kill-compilation))
336     (sh-mode               . (sh-compile        kill-compilation))
337     (csh-mode              . (csh-compile       kill-compilation))
338     (zsh-mode              . (zsh-compile       kill-compilation))
339     (perl-mode             . (perl-compile      kill-compilation))
340     (cperl-mode            . (perl-compile      kill-compilation))
341     (tcl-mode              . (tcl-compile       kill-compilation)) ; JWH
342     (python-mode           . (python-compile    kill-compilation)) ; BM
343     ;(message-mode          . (message-compile   kill-compilation))
344     (fundamental-mode      . (guess-compile     nil)) ; bound dynamically
345     (text-mode             . (guess-compile     nil)) ; itou
346     (indented-text-mode    . (guess-compile     nil)) ; itou
347     (compilation-mode      . (default-compile   kill-compilation)))
348   "Assoc list of compile/kill functions for some known modes.
349
350 Each element look like (MODE . (COMPILE-FUNCTION KILL-FUNCTION))
351  `mode-compile' will call COMPILE-FUNCTION and `mode-compile-kill'
352  KILL-FUNCTION if current major-mode is MODE.
353
354 If you want to add or modify a COMPILE-FUNCTION and it's associated
355 KILL-FUNCTION for MODE and don't want to hack `mode-compile' you could
356 do the following (it exists however a more subtle method for
357 modifying, this is left as an exercice for the reader :-):
358  (defun my-mode-compile() ...)
359  (defun my-mode-compile-kill() ...)
360  (setq mode-compile-modes-alist
361        (append '((my-mode . (my-mode-compile my-mode-compile-kill)))
362                mode-compile-modes-alist))"
363   :type '(repeat
364           (cons :tag "Association: mode/compilation functions"
365                 (function :tag "Mode")
366                 (list :tag "Compilation functions"
367                       (choice :tag "Function to run the compilation"
368                               (function-item :tag "Default" :value default-compile)
369                               (function-item :tag "Guess" :value guess-compile)
370                               (function-item :tag "Emacs lisp byte compilation" :value elisp-compile)
371                               (function :tag "Your choice, take care..."))
372                       (choice :tag "Function to kill a running compilation"
373                               (function-item :tag "Just kill" :value kill-compilation)
374                               (const :tag "Nothing -- use with guess-compile --" :value nil)
375                               (function-item :tag "To use with elisp-compile" :value keyboard-quit)
376                               ;; This item could not be selected due to a custom (hum) feature ...
377                               (function :tag "Your choice, take care..." :value nil)))))
378   :group 'compilation)
379
380 (defcustom mode-compile-filename-regexp-alist
381   ;; These could be in auto-mode-alist. But if you are like me
382   ;; and don't like these modes (prefear to edit these kind of
383   ;; files in text-mode) this is a nice way to compile them
384   ;; without to be bored with their associated modes.
385   '((mode-compile-makefile-regexp . makefile-mode)
386     ("\\.sh$"                     . sh-mode)
387     ("\\.csh$"                    . csh-mode)
388     ("\\.zsh$"                    . zsh-mode))
389   "Assoc list of major-modes for some filenames regexp.
390
391 Each element look like (REGEXP . MODE) This variable is really similar
392 to `auto-mode-alist' in the fact that it associate a MODE to a REGEXP
393 matching a filename. The only differences is that you are not obliged
394 to have the specified MODE available to use it (`guess-compile' use
395 it), the MODE is only a pointer to an assoq in
396 `mode-compile-modes-alist' to get the COMPILE-FUNCTION and the
397 KILL-FUNCTION. The REGEXP could be a form wich evaluate to a string.
398
399 To add a new filename regexp do the following:
400  (setq mode-compile-filename-regexp-alist
401        (append '((my-filename-regexp . some-mode-mode-compile-know)
402                mode-compile-modes-alist))"
403   :type '(repeat
404           (cons :tag "Association: filename/mode"
405            (choice :tag "Filename regexp match"
406             (regexp :tag "Regexp as a string")
407             (symbol :tag "Variable containing the regexp")
408             (sexp :tag "Form wich evaluate to a string"))
409            ;; I need to bind dynamicaly this with const, ideas??
410            ;;`(choice
411            ;; ,@(mapcar (lambda (x) `(const ,(car x))) mode-compile-modes-alist))))
412            (function :tag "Mode to use -- should be a valid assoq in mode-compile-modes-alist --")))
413   :group 'compilation)
414
415 (defcustom mode-compile-shell-alist
416   '(("sh"     .  sh-mode)
417     ("csh"    .  csh-mode)
418     ("zsh"    .  zsh-mode)
419     ("perl"   .  perl-mode)
420     ("tcl"    .   tcl-mode) ; JWH
421     ("python" . python-mode)) ; BM
422   "Assoc list of compile function for some known shells.
423
424 Each element look like (SHELL . MODE) This variable look like
425 `auto-mode-alist' in the fact that it associate a MODE to a name; A
426 SHELL name here. The main difference is that you are not obliged to
427 have the specified MODE available to use it (`guess-compile' use it),
428 the MODE is only a pointer to an assoq in `mode-compile-modes-alist'
429 to get the COMPILE-FUNCTION and the KILL-FUNCTION.
430
431 To add a new shell do the following:
432  (setq mode-compile-filename-shell-alist
433        (append '((my-shell-name . some-mode-mode-compile-know)
434                mode-compile-modes-alist))"
435   :type '(repeat
436           (cons :tag "Association: shell name/mode"
437            (string :tag "Shell name")
438            ;; I need to bind dynamicaly this with const, ideas??
439            ;;`(choice
440            ;; ,@(mapcar (lambda (x) `(const ,(car x))) mode-compile-modes-alist))))
441            (function :tag "Mode to use -- should be a valid assoq in mode-compile-modes-alist --")))
442   :group 'compilation)
443
444 ;;;###autoload
445 (defcustom mode-compile-make-program "make"
446   "*The `make' program used to process makefiles.
447
448 If you have GNU make installed with name \"gmake\" use it."
449   :type 'string
450   :group 'compilation)
451
452 (defcustom mode-compile-makefile-regexp
453   "\\(^[Mm]akefile\\|.*\\.[mM][aA]?[kK][eE]?\\.?.*$\\)"
454   "Regexp matching 'could be' makefiles filenames."
455   :type 'regexp
456   :group 'compilation)
457
458 (defcustom mode-compile-makefile-backups-regexp
459   "\\(\\(~\\|\\.[bB][aA][cC]?[kK]\\)$\\)\\|\\(\\(^\\|/\\)[.,][^/]+$\\)"
460   "Regexp to find if a Makefile is a backup or not"
461   :type 'regexp
462   :group 'compilation)
463
464 ;;;###autoload
465 (defcustom mode-compile-ignore-makefile-backups t
466   "*Tell mode compile to ignore makefiles backup files when selecting the Makefile to use."
467   :type 'boolean
468   :group 'compilation)
469
470 ;;;###autoload
471 (defvar mode-compile-default-make-options "-k"
472   "Default options to give to `make'.")
473 ;;;###autoload
474 (defcustom mode-compile-make-options (eval mode-compile-default-make-options)
475   "*Options to give to `make'.
476 This could be any form evaluating to a string.
477
478 Some people asked me a way to modify the make options everytime a
479 compilation command is launched, do that:
480  (defun my-mode-compile-ask-make-options()
481    \"*Hook called by mode-compile, asking for make options.\"
482    (interactive)
483    (read-string \"Make options: \"
484                 mode-compile-default-make-options))
485  (setq mode-compile-make-options
486            'my-mode-compile-ask-make-options)"
487   :type '(choice
488           string
489           (sexp :tag "Form evaluating to a string"))
490   :group 'compilation)
491
492 ;;;###autoload
493 (defcustom mode-compile-prefered-default-makerule 'none
494   "*Default makerule you would like to see in minibuffer as a default choice
495 when selecting the make rule to build.
496
497 Possible values are:
498 'none    -- let mode-compile deciding for you.
499 'all     -- try hard to show you the \"all\" rule.
500 'default -- try hard to show you the \"default\" rule.
501 'file    -- try to show you the name of the file which will be
502             result of compilation.
503 The 'none action is taken as default is something fail."
504   :type '(radio :tag "Symbol"
505                 (const :tag "None - Let mode compile made the choice" :value none)
506                 (const :tag "All - Show the \"all\" rule" :value all)
507                 (const :tag "Default - Show the \"default\" rule" :value default)
508                 (const :tag "File - Show the \"result file name\" rule" :value file))
509   :group 'compilation)
510
511 ;;;###autoload
512 (defcustom mode-compile-ignore-makerule-regexp nil
513   "*Makefile rules which must be ignored when building completion list.
514
515 For example if you want to remove all `files rules' set
516 it to: \"\\\\.\\\\([aoc]\\\\|s[ao][.0-9]*\\\\)\". "
517   :type '(choice (const :tag "none" :value nil)
518                  (const :tag "The `all files' rule" :value "\\.\\([aoc]\\|s[ao][.0-9]*\\)")
519                  regexp)
520   :group 'compilation)
521
522 ;;;###autoload
523 (defcustom mode-compile-save-all-p nil
524   "*Non-nil means save ALL the modified buffers without asking
525 before launching compilation command."
526   :type 'boolean
527   :group 'compilation)
528
529 ;;;###autoload
530 (defcustom mode-compile-always-save-buffer-p nil
531   "*Non-nil means save the current buffer without asking
532 before launching compilation command."
533   :type 'boolean
534   :group 'compilation)
535
536 ;;;###autoload
537 (defcustom mode-compile-never-edit-command-p nil
538   "*Non-nil means never ask to user to edit the compile command."
539   :type 'boolean
540   :group 'compilation)
541
542 ;; @@ Compilation in other frame vars ;;;
543 (defgroup compilation-frame nil
544   "Compile in another frame variables."
545   :group 'frames
546   :group 'compilation)
547
548 ;;;###autoload
549 (defcustom mode-compile-other-frame-p nil
550   "*Non-nil means compile in another frame.
551
552 A new Emacs FRAME is created and the compilation command is executed
553 in this other frame.  To specify the frame parameters see also
554 variable `mode-compile-frame-parameters-alist'."
555   :type 'boolean
556   :group 'compilation-frame)
557
558 (defcustom mode-compile-other-frame-name "COMPILATION"
559   "Name of mode-compile's other frame.
560
561 This name could be used in your .Xdefault or .Xresources file as:
562 Emacs.MODE-COMPILE-OTHER-FRAME-NAME.resource_to_be_set: ..."
563   :type 'string
564   :group 'compilation-frame)
565
566 (defconst mode-compile-default-frame-parameters
567   (list
568    (cons 'name   mode-compile-other-frame-name)
569    (cons 'width  85)  ; columns
570    (cons 'height 30)) ; lines
571    "Default parameters for mode-compile's other frame.")
572
573 (defvar mode-compile-frame-parameters-alist
574   (purecopy mode-compile-default-frame-parameters)
575   "Parameters for the new Compilation Screen created
576 if variable `mode-compile-other-frame-p' is non nil..
577
578 See also variable `mode-compile-default-frame-parameters' and
579 `mode-compile-other-frame-name'.
580
581 For informations about Screen/Frame parameters see:
582 - Info, Nodes: Lispref::Screen::Screen Parameters
583 - GNU Emacs Lisp Reference Manual, chapter 26 p375: Frames.")
584
585 ;; @@ Hooks ;;;
586
587 ;;;###autoload
588 (defcustom mode-compile-before-compile-hook nil
589   "Hook to be run before compile command is executed
590 when `mode-compile' is invoked."
591   :type 'hook
592   :group 'compilation)
593
594 ;;;###autoload
595 (defcustom mode-compile-after-compile-hook nil
596   "Hook to be run after compile command is executed
597 when `mode-compile' is invoked."
598   :type 'hook
599   :group 'compilation)
600
601 ;;;###autoload
602 (defcustom mode-compile-before-kill-hook nil
603   "Hook to be run before killing compile command is executed
604 when `mode-compile-kill' is invoked."
605   :type 'hook
606   :group 'compilation)
607
608 ;;;###autoload
609 (defcustom mode-compile-after-kill-hook nil
610   "Hook to be run after killing compile command is executed
611 when `mode-compile-kill' is invoked."
612   :type 'hook
613   :group 'compilation)
614
615 ;; @@ System dependencies ;;;
616
617 (defvar mode-compile-exe-file-ext
618   (cond
619    ((memq system-type '(ms-dos emx windows-95 windows-98 windows-nt)) ".exe")
620    (t ""))
621   "*Extension of executable files (with dot included)")
622
623 (defvar mode-compile-dir-separator-char
624   (cond
625    ;; MSDOSish file systems
626    ((memq system-type '(ms-dos emx windows-95 windows-98 windows-nt)) "\\")
627    ;; Unixish file systems
628    (t "/"))
629   "*Separator char between directories")
630
631 ;; @@ Facilities variables ;;;
632
633 ;;;###autoload
634 (defvar mode-compile-choosen-compiler nil
635   "*Global variable containing the name of the compiler
636 which will be used for compiling without makefile.
637
638  Could be used in combination with
639  (cc|c++|ada|f77)-default-compiler-options
640 to automaticaly choose the compiler specific options.
641
642 example:
643  (defun my-compiler-get-options()
644    (cond
645     ((string= mode-compile-choosen-compiler \"gcc\")
646       \"-Wall -pedantic-errors\")
647     ((string= mode-compile-choosen-compiler \"cc\")
648       \"cc options whatever they are...\")
649     (t
650      (message \"Don't know this compiler: %s\" mode-compile-choosen-compiler)
651      (read-string
652       (format \"Options for %s compiler: \" mode-compile-choosen-compiler)))))
653
654   (setq cc-default-compiler-options 'my-compiler-get-options)")
655
656 ;; @@ User level ;;;
657
658 ;;;###autoload
659 (defcustom mode-compile-expert-p nil
660   "*Non nil means `mode-compile' will not speaks too much.
661
662 See also variable variable mode-compile-reading-time."
663   :type 'boolean
664   :group 'compilation)
665
666 ;;;###autoload
667 (defcustom mode-compile-reading-time 1
668   "*Seconds to wait in verbose mode after printing a message.
669
670 In verbose mode mode-compile print too much messages that it is
671 allmost impossible to read them. Just setting this delay leave you the
672 time to read all the messages. If you don't want any delay set it to
673 `0'.
674
675 See also function sit-for."
676   :type 'integer
677   :group 'compilation)
678 \f
679
680 ;; @@ Remote compilation vars ;;;
681 (defgroup compilation-remote nil
682   "Remote compilations options."
683   :group 'compilation)
684
685 (defcustom mode-compile-remote-hosts-alist '()
686   "Alist of favourites hosts names and the username
687 to use to log on (HOSTNAME . USERNAME).
688
689 If USERNAME is a function it will be called with HOSTNAME as argument
690 and should return an USERNAME string (for example you could use
691 something like efs-get-user - not tested -), if it is nil the function
692 user-login-name will be used."
693   :type '(repeat
694           (cons
695            (string :tag "Hostname")
696            (choice
697             (const :tag "We'll use \'user-login-name" :value nil)
698             (string :tag "Username")
699             (function :tag "Function which return USERNAME given a HOSTNAME" :value efs-get-user))))
700   :group 'compilation-remote)
701
702 (defcustom mode-compile-remote-execute-command "rsh"
703   "The shell command used to run a command remotely.
704 \"rsh\" is the only choice I know but I'm far to know everything...
705
706  This variable is set automaticaly with the value of
707 remote-shell-program or efs-remote-shell-file-name at load time."
708   :type 'string
709   :group 'compilation)
710 (eval-when 'load
711   (cond
712    ((not (string= mode-compile-remote-execute-command "rsh"))
713     ;; user changed default
714     nil)
715    ;; Try to not multiply definitions of the same stuff
716    ;; in too many emacs lisp packages ...
717    ((and (boundp 'remote-shell-program) remote-shell-program)
718     (setq mode-compile-remote-execute-command remote-shell-program))
719    ((and (boundp 'efs-remote-shell-file-name) efs-remote-shell-file-name)
720     (setq mode-compile-remote-execute-command efs-remote-shell-file-name))
721    ))
722
723 (defcustom mode-compile-remote-execute-set-host-arg ""
724   "Argument To set the remote host name to the
725 mode-compile-remote-execute-command,
726
727 None is required for \"rsh\"."
728   :type 'string
729   :group 'compilation-remote)
730
731 (defcustom mode-compile-remote-execute-set-command-arg ""
732   "Argument to set the command to be run remotely to the
733 mode-compile-remote-execute-command.
734
735 None is required for \"rsh\"."
736   :type 'string
737   :group 'compilation-remote)
738
739 (defcustom mode-compile-remote-execute-set-username-arg "-l"
740   "Argument to set the username under which we will log on
741 on the remote host, to give to mode-compile-remote-execute-command."
742   :type 'string
743   :group 'compilation-remote)
744
745 (defcustom mode-compile-remote-execute-misc-args ""
746   "Misc additionnals arguments to give to the
747 mode-compile-remote-execute-command."
748   :type 'string
749   :group 'compilation-remote)
750
751 \f
752
753 ;; @@ c-mode compile variables ;;;
754 (defgroup compile-c nil
755   "C Compilation options."
756   :group 'c
757   :group 'compilation-lang)
758
759 (defcustom cc-compilers-list '( "gcc" "c89" "acc" "cc" )
760   "List of user's favourites C compilers in order of preferencies."
761   :type '(repeat (string :tag "C Compiler name"))
762   :group 'compile-c)
763
764 (defcustom cc-companion-file-regexp "\\(_[Pp]\\)?\\.[pP]?h"
765   "Regexp to find associated .c file from a .h."
766   :type 'regexp
767   :group 'compile-c)
768
769 (defcustom cc-default-compiler "cc"
770   "*Default C compiler to use when everything else fails.
771
772 This could be any form evaluating to a string, so you could map it to
773 a function asking you interactively to choose the compiler.
774
775 example:
776  (defun my-choose-compiler()
777    (read-string \"C compiler: \"))
778  (setq cc-compilers-list '()
779        cc-default-compiler 'my-choose-compiler)"
780   :type '(choice string function)
781   :group 'compile-c)
782
783 (defcustom cc-compiler-varenv "CC"
784   "Varenv indicating the C compiler to use."
785   :type 'string
786   :group 'compile-c)
787
788 (defcustom cc-cflags-varenv "CFLAGS"
789   "Varenv indicating the C compiler flags to use."
790   :type 'string
791   :group 'compile-c)
792
793 (defcustom cc-source-ext-list '( "c" )
794   "Extensions for C compileable source files."
795   :type '(repeat string)
796   :group 'compile-c)
797
798 (defcustom cc-headers-ext-list '( "h" )
799   "Extensions for C headers source files."
800   :type '(repeat string)
801   :group 'compile-c)
802
803 (defcustom cc-default-compiler-options "-g"
804   "*Default options to give to the C compiler.
805
806 This could be any form evaluating to a string.
807 See `mode-compile-choosen-compiler' variable."
808   :type '(choice
809           string
810           (sexp :tag "Form evaluating to a string"))
811   :group 'compile-c)
812
813 (defcustom cc-source-file-ext-regexp "\\.c"
814   "Regexp to find, from it's name, if a C file is compileable."
815   :type 'string
816   :group 'compile-c)
817
818 (defcustom cc-build-output-args t
819   "Build output-args for c-mode."
820   :type 'boolean
821   :group 'compile-c)
822
823 (defcustom cc-object-file-ext "o"
824   "Extension of objects file (result of compilation)
825 in c mode."
826   :type 'string
827   :group 'compile-c)
828
829 \f
830
831 ;; @@ java-mode compile variables ;;;
832 (defgroup compile-java nil
833   "Java compilation options."
834   :group 'compilation-lang)
835
836 (defcustom java-compilers-list '( "javac" )
837   "List of user's favourites java compilers in order of preferencies."
838   :type '(repeat (string :tag "Java Compiler name"))
839   :group 'compile-java)
840
841 (defcustom java-companion-file-regexp ""
842   "Regexp to find associated compileable Java companion file.
843
844 This is useless in Java because there do not exists uncompileable files."
845   :type 'regexp
846   :group 'compile-java)
847
848 (defcustom java-default-compiler "javac"
849   "*Default C compiler to use when everything else fails.
850
851 This could be any form evaluating to a string, so you could map it to
852 a function asking you interactively to choose the compiler.
853
854 example:
855  (defun my-choose-compiler()
856    (read-string \"Java compiler: \"))
857  (setq java-default-compiler 'my-choose-compiler)."
858   :type '(choice string function)
859   :group 'compile-java)
860
861 (defcustom java-compiler-varenv "JAVAC"
862   "Varenv indicating the C compiler to use."
863   :type 'string
864   :group 'compile-java)
865
866 (defcustom java-cflags-varenv "JAVAC_FLAGS"
867   "Varenv indicating the C compiler flags to use."
868   :type 'string
869   :group 'compile-java)
870
871 (defcustom java-source-ext-list '( "java" )
872   "Extensions for Java compileable source files."
873   :type '(repeat string)
874   :group 'compile-java)
875
876 (defcustom java-headers-ext-list '( "java" )
877   "Extensions for Java source files."
878   :type '(repeat string)
879   :group 'compile-java)
880
881 (defcustom java-default-compiler-options "-O"
882   "*Default options to give to the Java compiler.
883
884 This could be any form evaluating to a string.  See
885 `mode-compile-choosen-compiler' variable."
886   :type '(choice
887           string
888           (sexp :tag "Form evaluating to a string"))
889   :group 'compile-java)
890
891 (defcustom java-source-file-ext-regexp "\\.java"
892   "Regexp to find, from it's name, if a Java file is compileable."
893   :type 'regexp
894   :group 'compile-java)
895
896 (defcustom java-build-output-args nil
897   "Dont build output-args for Java-mode."
898   :type 'boolean
899   :group 'compile-java)
900
901 (defcustom java-object-file-ext "class"
902   "Extension of objects file (result of compilation)
903 in java mode."
904   :type 'string
905   :group 'compile-java)
906
907 \f
908
909 ;; @@ c++-mode compile variables ;;;
910 (defgroup compile-c++ nil
911   "C++ compilation options"
912   :group 'compilation-lang)
913
914 (defcustom c++-compilers-list '( "g++" "gcc" "CC" )
915   "List of user's favourites C++ compilers in order of preferencies."
916   :type '(repeat (string :tag "C++ Compiler name"))
917   :group 'compile-c++)
918
919 (defcustom c++-companion-file-regexp "\\(_[Pp]\\)?\\.\\([pP]?[Hh][Hh]?\\|[Hh]\\+\\+?\\)"
920   "Regexp to find associated compileable C++ companion file
921 from a header file."
922   :type 'regexp
923   :group 'compile-c++)
924
925 (defcustom c++-default-compiler "CC"
926   "*Default C++ compiler to use when everything else fails..
927
928 This could be any form evaluating to a string, so you could map it to
929 a function asking you interactively to choose the compiler.
930
931 example:
932  (defun my-choose-compiler()
933    (read-string \"C++ compiler: \"))
934  (setq c++-default-compiler 'my-choose-compiler)"
935   :type '(choice string function)
936   :group 'compile-c++)
937
938 (defcustom c++-compiler-varenv "CXX"
939   "Varenv indicating the C++ compiler to use."
940   :type 'string
941   :group 'compile-c++)
942
943 (defcustom c++-cflags-varenv "CXXFLAGS"
944   "Varenv indicating the C++ compiler flags to use."
945   :type 'string
946   :group 'compile-c++)
947
948 (defcustom c++-source-ext-list '( "cc" "C" "CC" "cpp" "cxx" "c++" "c+" )
949   "Extensions for C++ compileable source files."
950   :type '(repeat string)
951   :group 'compile-c++)
952
953 (defcustom c++-headers-ext-list '( "H" "hh" "HH" "h++" "h+" "h" "hpp" "hxx" )
954   "Extensions for C++ headers source files."
955   :type '(repeat string)
956   :group 'compile-c++)
957
958 (defcustom c++-default-compiler-options "-g"
959   "*Default options to give to the C++ compiler.
960 This could be any form evaluating to a string.  See
961 `mode-compile-choosen-compiler' variable."
962   :type '(choice
963           string
964           (sexp :tag "Form evaluating to a string"))
965   :group 'compile-c++)
966
967 (defcustom c++-source-file-ext-regexp "\\.\\(cc\\|CC?\\|c\\+\\+?\\|cpp\\|cxx\\)"
968   "Regexp to find, from it's name, if a C++ file is compileable."
969   :type 'regexp
970   :group 'compile-c++)
971
972 (defcustom c++-build-output-args t
973   "Build output-args for c++-mode."
974   :type 'boolean
975   :group 'compile-c++)
976
977 (defcustom c++-object-file-ext "o"
978   "Extension of objects file (result of compilation)
979 in c++ mode."
980   :type 'string
981   :group 'compile-c++)
982
983 \f
984
985 ;; @@ ada-mode compile variables ;;;
986 (defgroup compile-ada nil
987   "Ada compilation options"
988   :group 'compilation-lang)
989
990 (defcustom ada-compilers-list
991   '( "gcc" "gnat" "ada" )
992   "List of user's favourites Ada compilers in order of preferencies."
993   :type '(repeat (string :tag "Ada Compiler name"))
994   :group 'compile-ada)
995
996 (defcustom ada-companion-file-regexp ""
997   "Regexp to find associated compileable Ada companion file from a spec file.
998
999 This is useless in Ada because there do not exists uncompileable files."
1000   :type 'regexp
1001   :group 'compile-ada)
1002
1003 (defcustom ada-default-compiler "ada"
1004   "*Default Ada compiler to use when everything else fails.
1005
1006 This could be any form evaluating to a string, so you could map it to
1007 a function asking you interactively to choose the compiler.
1008
1009 example:
1010  (defun my-choose-compiler()
1011    (read-string \"Ada compiler: \"))
1012  (setq ada-default-compiler 'my-choose-compiler)"
1013   :type '(choice string function)
1014   :group 'compile-ada)
1015
1016 (defcustom ada-compiler-varenv "ADA"
1017   "Varenv indicating the Ada compiler to use."
1018   :type 'string
1019   :group 'compile-ada)
1020
1021 (defcustom ada-aflags-varenv "AFLAGS"
1022   "Varenv indicating the Ada compiler flags to use."
1023   :type 'string
1024   :group 'compile-ada)
1025
1026 (defcustom ada-source-ext-list '( "ads" "adb" "ada" "a" )
1027   "Extensions for Ada compileable source files."
1028   :type '(repeat string)
1029   :group 'compile-ada)
1030
1031 (defcustom ada-headers-ext-list '( "ads" "ada" "a" )
1032   "Extensions for Ada spec source files."
1033   :type '(repeat string)
1034   :group 'compile-ada)
1035
1036 (defcustom ada-default-compiler-options "-g"
1037   "*Default options to give to the Ada compiler.
1038
1039 This could be any form evaluating to a string.  See
1040 `mode-compile-choosen-compiler' variable."
1041   :type '(choice
1042           string
1043           (sexp :tag "Form evaluating to a string"))
1044   :group 'compile-ada)
1045
1046 (defcustom ada-source-file-ext-regexp "\\.\\(ad[abs]\\|a\\)"
1047   "Regexp to find, from it's name, if an Ada file is compileable.
1048
1049 This is useless in Ada because there do not exists uncompileable files."
1050   :type 'regexp
1051   :group 'compile-ada)
1052
1053 (defcustom ada-build-output-args t
1054   "Build output-args for ada-mode."
1055   :type 'boolean
1056   :group 'compile-ada)
1057
1058 (defcustom ada-object-file-ext "o"
1059   "Extension of objects file (result of compilation)
1060 in ada mode."
1061   :type 'string
1062   :group 'compile-ada)
1063
1064 \f
1065
1066 ;; @@ fortran-mode compile variables ;;;
1067 (defgroup compile-fortran nil
1068   "Fortran compilation options"
1069   :group 'compilation-lang)
1070
1071 (defcustom f77-compilers-list '( "f77" "fc" )
1072   "List of user's favourite Fortran compilers in order of preferencies."
1073   :type '(repeat (string :tag "C Compiler name"))
1074   :group 'compile-fortran)
1075
1076 (defcustom f77-companion-file-regexp "\\(_[Pp]\\)?\\.[pP]?inc"
1077   "Regexp to find associated .f file from a .inc."
1078   :type 'regexp
1079   :group 'compile-fortran)
1080
1081 (defcustom f77-default-compiler "f77"
1082   "*Default fortran compiler to use when everything else fails..
1083
1084 This could be any form evaluating to a string, so you could map it to
1085 a function asking you interactively to choose the compiler.
1086
1087 example:
1088  (defun my-choose-compiler()
1089    (read-string \"Fortran compiler: \"))
1090  (setq f77-default-compiler 'my-choose-compiler)"
1091   :type '(choice string function)
1092   :group 'compile-fortran)
1093
1094 (defcustom f77-compiler-varenv "F77"
1095   "Varenv indicating the fortran compiler to use."
1096   :type 'string
1097   :group 'compile-fortran)
1098
1099 (defcustom f77-cflags-varenv "FCOPTS"
1100   "Varenv indicating the fortran compiler flags to use."
1101   :type 'string
1102   :group 'compile-fortran)
1103
1104 (defcustom f77-source-ext-list '( "f" "F" "for" "For" )
1105   "Extensions for fortran compileable source files."
1106   :type '(repeat string)
1107   :group 'compile-fortran)
1108
1109 (defcustom f77-headers-ext-list '( "inc" "h")
1110   "Extensions for fortran include files."
1111   :type '(repeat string)
1112   :group 'compile-fortran)
1113
1114 (defcustom f77-default-compiler-options "-w66 -a"
1115   "*Default options to give to the fortran compiler.
1116
1117 This could be any form evaluating to a string.  See
1118 `mode-compile-choosen-compiler' variable."
1119   :type '(choice
1120           string
1121           (sexp :tag "Form evaluating to a string"))
1122   :group 'compile-fortran)
1123
1124 (defcustom f77-source-file-ext-regexp "\\.\\([Ff]\\|for\\)"
1125   "Regexp to find, from it's name, if a fortran file is compileable."
1126   :type 'regexp
1127   :group 'compile-fortran)
1128
1129 (defcustom f77-build-output-args t
1130   "Build output-args for f77-mode."
1131   :type 'boolean
1132   :group 'compile-fortran)
1133
1134 (defcustom f77-object-file-ext "o"
1135   "Extension of objects file (result of compilation)
1136 in Fortran mode."
1137   :type 'string
1138   :group 'compile-fortran)
1139
1140 \f
1141
1142 ;; @@ sh-mode compile variables ;;;
1143 (defgroup compile-sh nil
1144   "Sh (Bourne Shell scripts) compilation options"
1145   :group 'compilation-script)
1146
1147 (defcustom sh-command "sh"
1148   "Command to run sh scripts"
1149   :type 'string
1150   :group 'compile-sh)
1151
1152 (defcustom sh-dbg-flags "-fvx"
1153   "*Flags to give to sh for debugging a Bourne Shell script.
1154
1155 The -f flag must always be present."
1156   :type 'string
1157   :group 'compile-sh)
1158
1159 (defvar sh-compilation-error-regexp-alist nil
1160   ;; I'd never seen a Bourne shell returning file+line where a syntax
1161   ;; error occured.
1162   "Alist that specifies how to match errors in sh output.
1163
1164 See variable compilation-error-regexp-alist for more details.")
1165 \f
1166
1167 ;; @@ csh-mode compile variables ;;;
1168 (defgroup compile-csh nil
1169   "Csh (C Shell) compilation options"
1170   :group 'compilation-script)
1171
1172 (defcustom csh-command "csh"
1173   "Command to run csh scripts"
1174   :type 'string
1175   :group 'compile-csh)
1176
1177 (defcustom csh-dbg-flags "-fVX"
1178   "*Flags to give to csh for debugging a C Shell script.
1179
1180 The -f flag must always be present."
1181   :type 'string
1182   :group 'compile-csh)
1183
1184 (defvar csh-compilation-error-regexp-alist nil
1185   ;; I'd never seen a C shell returning file+line where a syntax
1186   ;; error occured.
1187   "Alist that specifies how to match errors in csh output.
1188
1189 See variable compilation-error-regexp-alist for more details.")
1190 \f
1191
1192 ;; @@ zsh-mode compile variables ;;;
1193 (defgroup compile-zsh nil
1194   "Zsh (Z Shell scripts) compilation options"
1195   :group 'compilation-script)
1196
1197 (defcustom zsh-command "zsh"
1198   "Command to run zsh scripts"
1199   :type 'string
1200   :group 'compile-zsh)
1201
1202 (defcustom zsh-dbg-flags "-nCvx"
1203   "*Flags to give to zsh for debugging a Z Shell script."
1204   :type 'string
1205   :group 'compile-zsh)
1206
1207 (defvar zsh-compilation-error-regexp-alist nil
1208   ;; I'd never seen a Z shell returning file+line where a syntax
1209   ;; error occured.
1210   "Alist that specifies how to match errors in csh output.
1211
1212 See variable compilation-error-regexp-alist for more details.")
1213 \f
1214
1215 ;; @@ tcl-mode compile variables - JWH ;;;
1216 (defgroup compile-tcl nil
1217   "Tcl compilation options"
1218   :group 'compilation-script)
1219
1220 (defcustom tcl-command "wish"
1221   "Command to run tcl scripts"
1222   :type 'string
1223   :group 'compile-tcl)
1224
1225 (defcustom tcl-dbg-flags ""
1226   "*Flags to give to tcl -- none."
1227   :type 'string
1228   :group 'compile-tcl)
1229
1230 (defvar tcl-compilation-error-regexp-alist
1231   ;; TK  (file "/directory-path/filename.tcl" line XY)
1232   '(
1233     ("file \"\\([^ ]+\\)\" line \\([0-9]+\\)[)]" 1 2)
1234     )
1235   "Alist that specifies how to match errors in tcl output.
1236
1237 See variable compilation-error-regexp-alist for more details.")
1238 \f
1239
1240 ;; @@ python-mode compile variables - BM ;;;
1241 (defgroup compile-python nil
1242   "Python compilation options"
1243   :group 'compilation-script)
1244
1245 (defcustom python-command "python"
1246   "Command to run python scripts"
1247   :type 'string
1248   :group 'compile-python)
1249
1250 (defcustom python-dbg-flags ""
1251   "*Flags to give to python -- none."
1252   :type 'string
1253   :group 'compile-phthon)
1254
1255 (defvar python-compilation-error-regexp-alist
1256   ;; TK  (file "/directory-path/filename.tcl" line XY in ZZZ)
1257   '(
1258     ("File \"\\([^ ]+\\)\", line \\([0-9]+\\).*" 1 2)
1259     )
1260   "Alist that specifies how to match errors in python output.
1261
1262 See variable compilation-error-regexp-alist for more details.")
1263 \f
1264
1265 ;; @@ perl-mode compile variables ;;;
1266 (defgroup compile-perl nil
1267   "Perl compilation options"
1268   :group 'compilation-script)
1269
1270 (defcustom perl-command "perl"
1271   "Command to run perl."
1272   :type 'string
1273   :group 'compile-perl)
1274
1275 (defcustom perl-dbg-flags "-w"
1276   "*Flags to give to perl for debugging a Perl script."
1277   :type 'string
1278   :group 'compile-perl)
1279
1280 (defvar perl-compilation-error-regexp-alist
1281   ;; Contributed by Martin Jost
1282   '(
1283     ;; PERL 4
1284     ("in file \\([^ ]+\\) at line \\([0-9]+\\).*" 1 2)
1285     ;; PERL 5   Blubber at FILE line XY, <XY> line ab.
1286     ("at \\([^ ]+\\) line \\([0-9]+\\)," 1 2)
1287     ;; PERL 5   Blubber at FILE line XY.
1288     ("at \\([^ ]+\\) line \\([0-9]+\\)." 1 2)
1289     )
1290   ;; This look like a paranoiac regexp: could anybody find a better one? (which WORK).
1291   ;;'(("^[^\n]* \\(file\\|at\\) \\([^ \t\n]+\\) [^\n]*line \\([0-9]+\\)[\\.,]" 2 3))
1292   "Alist that specifies how to match errors in perl output.
1293
1294 See variable compilation-error-regexp-alist for more details.")
1295 \f
1296
1297 ;; @@ emacs lisp compile variables ;;;
1298
1299 ;;;###autoload
1300 (defcustom emacs-lisp-byte-compile-dir-interactive-p t
1301   "*Non-nil means when byte-compiling a directory ask for each file
1302 needing to be recompiled or not."
1303   :type 'boolean
1304   :group 'compilation-elisp)
1305 (define-obsolete-variable-alias
1306   'mode-compile-byte-compile-dir-interactive-p
1307   'emacs-lisp-byte-compile-dir-interactive-p)
1308
1309 (defcustom emacs-lisp-sources-regexp
1310   (cond
1311    ((boundp 'emacs-lisp-file-regexp)
1312     emacs-lisp-file-regexp)
1313    (t
1314     "\\.el$"))
1315   "Regexp to find emacs lisp sources files."
1316   :type 'regexp
1317   :group 'compilation-elisp)
1318
1319 (defcustom emacs-lisp-bytecomp-ext "c"
1320   "Extension added to byte-compiled emacs sources files."
1321   :type 'string
1322   :group 'compilation-elisp)
1323 \f
1324
1325 ;; @@ Misc declarations ;;;
1326
1327 ;;;###autoload
1328 (defconst mode-compile-version "2.28"
1329   "Current version of mode-compile package.
1330
1331 mode-compile.el,v 2.28 2003/04/01 13:52:47 boubaker Exp
1332 Please send bugs-fixes/contributions/comments to boubaker@cena.fr")
1333
1334 (defconst mode-compile-help-address "heddy.Boubaker@cena.fr"
1335   "E-Mail address of mode-compile maintainer.")
1336 \f
1337
1338 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1339 ;; @ No user modifiable stuff below this line ;;;
1340 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
1341
1342 ;; Save old compile function. In case someone will bound
1343 ;; mode-compile on 'compile.
1344 (or (fboundp 'mc--compile-sav)
1345     (if (fboundp 'compile)
1346         (progn
1347           (fset 'mc--compile-sav (symbol-function 'compile))
1348           (put 'compile 'compile-saved-on-mc--compile-sav t))
1349       (error "`compile' function not known to be defined...")))
1350
1351 ;; @@ Internals variables and constants ;;;
1352
1353 ;; Mode specific
1354 (defvar mc--comp-lst          nil) ; c-mode,c++-mode,ada-mode,fortran-mode
1355 (defvar mc--def-comp          nil) ; itou
1356 (defvar mc--compfile-regexp   nil) ; itou
1357 (defvar mc--comp-varenv       nil) ; itou
1358 (defvar mc--comp-options      nil) ; itou
1359 (defvar mc--cflags-varenv     nil) ; itou
1360 (defvar mc--source-ext-lst    nil) ; itou
1361 (defvar mc--head-ext-lst      nil) ; itou
1362 (defvar mc--source-ext-regexp nil) ; itou
1363 (defvar mc--build-op-args     nil) ; itou
1364 (defvar mc--outfile-ext       nil) ; itou
1365
1366 ;; remote stuff
1367 (defvar mc--efs-path-list       nil)
1368 (defvar mc--remote-host         nil)
1369 (defvar mc--remote-host-history nil)
1370 (defvar mc--remote-username     nil)
1371 (defvar mc--remote-command      nil)
1372 (defvar mc--remote-pathname     nil)
1373
1374 ;; Frames/Windows stuff
1375 (defvar mc--other-frame nil)
1376 (defvar mc--ws (or
1377                 (and (fboundp 'console-type) (console-type))
1378                 (and (fboundp 'device-type)  (device-type))
1379                 window-system))
1380
1381 (defvar mc--compile-command nil)
1382 ;; Compile command used when no makefile has been found.
1383 ;; This variable is buffer local to keep history for read-string.
1384 ;; Unfortunately not a real history, keep only memory of
1385 ;; the last compile command used.
1386 (make-variable-buffer-local 'mc--compile-command)
1387
1388 (defvar mc--kill-compile nil)
1389 ;; kill-compile command bound dynamically by `guess-compile'.
1390 (make-variable-buffer-local 'mc--kill-compile)
1391
1392 (defvar mc--selected-makefile nil)
1393 (defvar mc--selected-makefile-history nil)
1394 ;; User selected makefile among the list, to run make with.
1395 ;; This variable is buffer local to keep history for completing-read
1396 ;; Unfortunately not a real history, keep only memory of
1397 ;; the last makefile used.
1398 (make-variable-buffer-local 'mc--selected-makefile)
1399
1400 (defvar mc--selected-makerule nil)
1401 (defvar mc--selected-makerule-history nil)
1402 ;; User selected make rule to rebuild.
1403 ;; This variable is buffer local to keep history for completing-read
1404 ;; Unfortunately not a real history, keep only memory of
1405 ;; the last makerule used.
1406 (make-variable-buffer-local 'mc--selected-makerule)
1407
1408 (defconst mc--find-C-main-regexp
1409   "^[ \t]*\\(int\\|void\\)?[ \t\n]*main[ \t\n]*\(+" )
1410 ;; Regexp to find the main() function in a C/C++ file
1411
1412 (defconst mc--makefile-rules-regexp
1413   "^\n*\\([^.$ \t#\n][^$ \t#\n:]*\\)[ \t]*:")
1414 ;; Regexp to extract makefiles rules.
1415 ;; But only those not containing references to $(VARIABLES)
1416 ;; and not starting with `.'
1417
1418 (defvar mc--makefile-rules nil)
1419 ;; List of all rules extracted from makefile
1420 (make-variable-buffer-local 'mc--makefile-rules)
1421
1422 (defvar mc--mkfl-buffer-tick nil)
1423 ;; Tick counter for the buffer at the time of the rules extraction.
1424 (make-variable-buffer-local 'mc--mkfl-buffer-tick)
1425
1426 (defvar mc--shell-args nil)
1427 ;; Shell arguments for the script to debug.
1428 ;; This variable is buffer local to keep history for read-string.
1429 ;; Unfortunately not a real history, keep only memory of
1430 ;; the last shell arguments used.
1431 (make-variable-buffer-local 'mc--shell-args)
1432
1433 ;; nil in GNU FSF Emacs, >= 0 in GNU Lucid Emacs/XEmacs
1434 (defconst mc--lucid-emacs-p (or (string-match "Lucid"  emacs-version)
1435                                 (string-match "XEmacs" emacs-version)))
1436
1437 ;; @@ Internals functions and macros ;;;
1438
1439 (if (not (fboundp 'defsubst))
1440     ;; Emacs 18
1441     (fset 'defsubst (symbol-function 'defun)))
1442
1443 (defun mc--compile (compile-command)
1444   ;; Call compile with the compile command
1445   ;; but append the remote-command before
1446   (if (null mc--remote-command)
1447       ;; local compile
1448       (mc--compile-sav compile-command)
1449     ;; remote compile
1450     (let ((thisdir (expand-file-name (or default-directory "~"))))
1451       (mc--compile-sav
1452        (concat
1453         ;; The command to lauch remote commands
1454         mc--remote-command
1455         ;; Change to this buffer directory ...
1456         "'( cd " thisdir " ; "
1457         ;; then run the compile command
1458         compile-command " )'")))))
1459
1460 (defsubst mc--msg (msg &rest args)
1461   ;; Print MSG with ARGS and wait to let time to user
1462   ;; to read the message in minibuffer.
1463   (cond ((not mode-compile-expert-p)
1464          (apply 'message (concat "mode-compile: " msg) args)
1465          (sit-for mode-compile-reading-time))))
1466
1467 (cond
1468  ;; Check availaibles frames functions
1469  ((fboundp 'make-frame)
1470   ;; GNU Emacs
1471   (fset 'mc--make-frame         (symbol-function 'make-frame))
1472   (fset 'mc--select-frame       (symbol-function 'select-frame))
1473   (fset 'mc--frame-live-p       (symbol-function 'frame-live-p))
1474   (fset 'mc--make-frame-visible (symbol-function 'make-frame-visible))
1475   (fset 'mc--raise-frame        (symbol-function 'raise-frame)))
1476  ((fboundp 'make-screen)
1477   ;; XEmacs
1478   (fset 'mc--make-frame         (symbol-function 'make-screen))
1479   (fset 'mc--select-frame       (symbol-function 'select-screen))
1480   (fset 'mc--frame-live-p       (symbol-function 'screen-live-p))
1481   (fset 'mc--make-frame-visible (symbol-function 'make-screen-visible))
1482   (fset 'mc--raise-frame        (symbol-function 'raise-screen)))
1483  ((fboundp 'new-screen)
1484   ;; Lucid Emacs/obsolete
1485   (fset 'mc--make-frame         (symbol-function 'new-screen))
1486   (fset 'mc--select-frame       (symbol-function 'select-screen))
1487   (fset 'mc--frame-live-p       (symbol-function 'screen-live-p))
1488   (fset 'mc--make-frame-visible (symbol-function 'make-screen-visible))
1489   (fset 'mc--raise-frame        (symbol-function 'raise-screen))))
1490
1491 (defsubst mc--funcall (command &rest params)
1492   ;; Run command with params in another frame or not:
1493   ;; only if user ask for it and if window system is X
1494   ;; (maybe test window-system is set will be enought?).
1495   (cond ((and (eq mc--ws 'x)
1496               mode-compile-other-frame-p)
1497          ;; switch to another frame
1498          (mc--msg "Switching to another frame to compile...")
1499          (let ((buffer   (current-buffer))
1500                (win-attr (or mode-compile-frame-parameters-alist
1501                              mode-compile-default-frame-parameters))
1502                (frame   (cond ((fboundp 'mc--frame-live-p)
1503                                 (if (mc--frame-live-p mc--other-frame)
1504                                     mc--other-frame
1505                                   nil))
1506                                (t
1507                                 (mc--msg "Don't know how to check frame existence.")
1508                                 nil))))
1509            (cond ((fboundp 'mc--make-frame)
1510                   (mc--select-frame (or frame
1511                                          (setq mc--other-frame
1512                                                (mc--make-frame win-attr))))
1513                   ;; I really don't understand why the 3 following
1514                   ;; are necessary (raise-frame must be enought?).
1515                   (mc--make-frame-visible mc--other-frame)
1516                   (mc--raise-frame        mc--other-frame)
1517                   (switch-to-buffer        buffer))
1518                  (t
1519                   (mc--msg "Don't know how to create a new frame."))))))
1520   ;; Just run the command with it's parameters
1521   (apply command params))
1522
1523 (defun mc--byte-compile-buffer()
1524   (if (fboundp 'byte-compile-buffer) (byte-compile-buffer)
1525     ;; No byte-compile-buffer
1526     ;; Save current-buffer in a temporary file and byte-compile it.
1527     (let ((tmp-file (concat (or (getenv "TMPDIR")
1528                                 (concat mode-compile-dir-separator-char "tmp"))
1529                             mode-compile-dir-separator-char (make-temp-name "mc--"))))
1530       (save-restriction
1531         (widen)
1532         (write-region (point-min) (point-max) tmp-file)
1533         (condition-case err
1534             (byte-compile-file tmp-file)
1535           ;; handler
1536           (error (mc--msg "Failing to byte-compile %s, #error %s"
1537                           (buffer-name) err)))
1538         (delete-file tmp-file)
1539         (let ((elc-file (concat tmp-file emacs-lisp-bytecomp-ext)))
1540           (if (file-writable-p elc-file)
1541               (condition-case err
1542                   (delete-file elc-file)
1543                 ;; handler
1544                 (error (mc--msg "Failing to delete %s, #error %s"
1545                                 elc-file err)))))
1546         (message nil))))) ; to clean minibuffer
1547
1548 (fset 'mc--member
1549       (if (fboundp 'member)
1550           (symbol-function 'member)
1551         ;; No member function
1552         (function
1553          (lambda (elt list)
1554            (catch 'elt-is-member
1555              (while list
1556                (if (equal elt (car list))
1557                    (throw 'elt-is-member list))
1558                (setq list (cdr list))))))))
1559
1560 (fset 'mc--run-hooks
1561       (if (fboundp 'run-hooks)
1562           (symbol-function 'run-hooks)
1563         ;; No run-hooks
1564         (function
1565          (lambda (hooklist)
1566            (mapcar '(lambda (x)
1567                       ;; report an error if x not a function
1568                       (funcall x))
1569                    hooklist)))))
1570
1571 (defsubst mc--read-string (prompt &optional initial-contents)
1572   ;; On Lucid Emacs I use compile-history as 3rd argument but
1573   ;; no history is possible with GNU emacs.
1574   (if mc--lucid-emacs-p
1575       (read-string prompt initial-contents 'compile-history)
1576     (read-string prompt initial-contents)))
1577
1578 (defmacro mc--eval (sym &optional arg)
1579   ;; Evaluate symbol
1580   (` (cond
1581       ((and (symbolp (, sym))
1582             (fboundp (, sym)))
1583        (funcall (, sym) (, arg)))
1584       (t
1585        (eval (, sym))))))
1586
1587 (defmacro mc--common-completion (alist)
1588   ;; Return the greatest common string for all
1589   ;; possible completions in alist.
1590   (` (try-completion "" (, alist))))
1591
1592 (defun mc--byte-recompile-files (files)
1593   ;; Byte recompile all FILES which are older than their
1594   ;; .elc files in the current directory
1595   (let ((tmp-fl files))
1596     (while (car-safe tmp-fl)
1597       (let* ((el-file  (car tmp-fl))
1598              (elc-file (concat el-file emacs-lisp-bytecomp-ext)))
1599         (mc--msg "Checking file %s ..." el-file)
1600         ;; is el-file newer than elc-file (if exists)
1601         (if (and (file-newer-than-file-p el-file elc-file)
1602                  (or (not emacs-lisp-byte-compile-dir-interactive-p)
1603                      (y-or-n-p (format "byte-recompile file %s? " el-file))))
1604             (condition-case err
1605                 (byte-compile-file el-file)
1606               ;; handler
1607               (error (mc--msg "Failing to byte-compile %s, #error %s"
1608                               el-file err))))
1609         (setq tmp-fl (cdr-safe tmp-fl))))
1610     (mc--msg "All files processed")))
1611
1612 (defun mc--which (file)
1613   ;; Find an executable FILE in exec-path
1614   (if (not (stringp file))
1615       (error "mc--which: nil FILE arg"))
1616   (if mc--lucid-emacs-p
1617       ;; Some emacses don't have locate-file some have...
1618       ;; Lucid have it in standard, some others (GNU) have it
1619       ;; (add-on pkg) but the syntax is not always consistent...
1620 ;      (locate-file file exec-path nil 1)
1621       (locate-file file exec-path mode-compile-exe-file-ext 1)
1622     (let ((tmp-p-lst  exec-path)
1623           (found      nil)
1624           (file-found nil))
1625       (while (and (car-safe tmp-p-lst)
1626                   (not (setq found
1627                              (file-executable-p
1628                               (setq file-found
1629                                     (concat (car tmp-p-lst)
1630                                             mode-compile-dir-separator-char
1631                                             file
1632                                             mode-compile-exe-file-ext))))))
1633         (setq tmp-p-lst (cdr-safe tmp-p-lst)))
1634       (if found file-found nil))))
1635
1636 (defun mc--find-compiler ()
1637   ;; Find user's favourite mode compiler
1638   (mc--msg "Searching for your favourite %s compiler ..." mode-name)
1639   (let ((tmp-comp-lst mc--comp-lst)
1640         (compiler     nil))
1641     (or (getenv mc--comp-varenv)
1642         (progn
1643           (while (and tmp-comp-lst
1644                       (not (setq compiler
1645                                  (mc--which (car tmp-comp-lst)))))
1646             (setq tmp-comp-lst (cdr tmp-comp-lst)))
1647           (file-name-nondirectory (or compiler (mc--eval mc--def-comp)))))))
1648
1649 (defun mc--find-to-compile-file (&optional fname)
1650   ;; Find the name of the file to compile.
1651   (let ((file-name (or fname
1652                        (buffer-file-name)
1653                        (error "Compilation abort: Buffer %s has no filename."
1654                               (buffer-name))))
1655         (assoc-file nil)
1656         (found      nil)
1657         (pos        0))
1658     (cond
1659      ((string-match mc--source-ext-regexp file-name)
1660       ;; buffer is a compileable file
1661       (file-name-nondirectory file-name))
1662
1663      ((setq pos (string-match mc--compfile-regexp file-name))
1664       ;; Buffer is not a compileable file, try to find associated
1665       ;; compileable file.
1666       (let ((tmp-ext-lst mc--source-ext-lst))
1667         (mc--msg "Looking for a compileable companion file for %s..."
1668                  (file-name-nondirectory file-name))
1669         (while (and tmp-ext-lst
1670                     (not (setq found
1671                                (file-readable-p
1672                                 (setq assoc-file
1673                                       (concat
1674                                        (substring file-name 0 pos)
1675                                        "." (car tmp-ext-lst)))))))
1676           (setq tmp-ext-lst (cdr tmp-ext-lst))))
1677       (if found
1678           ;; A compileable companion source file found
1679           (file-name-nondirectory assoc-file)
1680         ;; No compileable companion source file found
1681         (mc--msg "Couldn't find any compileable companion file for %s ..."
1682                  (file-name-nondirectory file-name))
1683         nil))
1684
1685      (t
1686       ;; Buffer has an unknown file extension
1687       ;; Could I be more cool?
1688       (error "Compilation abort: Don't know how to compile %s."
1689              (file-name-nondirectory file-name))))))
1690
1691 (defun mc--guess-compile-result-fname (infile)
1692   ;; Try to guess if outfile will be an object file or
1693   ;; an executable file by grepping for `main()' in INFILE.
1694   (let ((base-fname
1695          (substring infile 0
1696                     (string-match mc--source-ext-regexp infile))))
1697     (save-excursion
1698       ;; Create a temporary buffer containing infile contents
1699       (set-buffer (find-file-noselect infile))
1700       (save-excursion
1701         (save-restriction
1702           (widen)
1703           (goto-char (point-min))
1704           ;; Grep into tmp buffer for main function
1705           ;; THIS WILL NOT WORK FOR PROGRAMMING LANGAGES
1706           ;; WHICH ARE NOT C DIALECTS:
1707           ;; In non C-ish modes I hope this regexp will never be found :-(
1708           (if (re-search-forward mc--find-C-main-regexp (point-max) t)
1709               (concat base-fname mode-compile-exe-file-ext)
1710             (concat base-fname "." mc--outfile-ext)))))))
1711
1712 (defun mc--build-output-args (infile)
1713   ;; Build output arguments for compile command by scanning INFILE.
1714   (mc--msg "Looking into %s to build compile command ..." infile)
1715   (let ((out-file (mc--guess-compile-result-fname infile)))
1716     (concat (if (string-match
1717                  (concat "\\." mc--outfile-ext "$")
1718                  out-file)
1719                 ;; outfile will be an object file
1720                 " -c "
1721               ;; outfile will be an executable file
1722               " ")
1723             infile " -o " out-file )))
1724
1725 (defun mc--set-remote-cmd (remote-host &optional username pathname)
1726   ;; Check validity of remote-host or ask one to user
1727   ;; Then build the first part of the remote command
1728   (if (stringp remote-host)
1729       ;; Arg is the remote host name
1730       (let ((host-infos (assoc remote-host
1731                                mode-compile-remote-hosts-alist)))
1732         (setq mc--remote-host
1733               remote-host)
1734         (setq mc--remote-username
1735               (or username
1736                   (let ((usrnam (cdr host-infos)))
1737                     (if usrnam
1738                         (cond
1739                          ((stringp usrnam)
1740                           usrnam)
1741                          ((functionp usrnam)
1742                           ;; usrnam is a function call it with hostname arg
1743                           (funcall usrnam mc--remote-host))
1744                          (t
1745                           ;; What's that??
1746                           (mc--msg "%s is not a valid option using user-login-name" (pp-to-string usrnam))
1747                           (user-login-name)))
1748                       (user-login-name)))))
1749         (setq mc--remote-pathname pathname)
1750         ;; Add host to the user's list
1751         (or host-infos
1752             (setq mode-compile-remote-hosts-alist
1753                   (append (list (list remote-host))
1754                           mode-compile-remote-hosts-alist)))
1755         ;; Prepare the command
1756         (setq mc--remote-command
1757               (concat
1758                ;; "rsh host -l username"
1759                mode-compile-remote-execute-command           " "
1760                mode-compile-remote-execute-set-host-arg      " "
1761                mc--remote-host                               " "
1762                mode-compile-remote-execute-set-username-arg  " "
1763                mc--remote-username                           " "
1764                mode-compile-remote-execute-misc-args         " "
1765                mode-compile-remote-execute-set-command-arg   " "
1766                 )))
1767     ;; Arg is: Ask to user then check
1768     (let ((rhost (completing-read
1769                   "Remote host to compile to: "
1770                   mode-compile-remote-hosts-alist
1771                   nil nil
1772                   ;; Initial contents
1773                   (or mc--remote-host
1774                       (car-safe (car-safe mode-compile-remote-hosts-alist)))
1775                   mc--remote-host-history)))
1776       (or (string= rhost "")
1777           (mc--set-remote-cmd rhost)))))
1778
1779 ;(defmacro mc--makefile-test-p (makefile)
1780 ;  (` (and (, makefile)
1781 ;          (not (string-equal     (, makefile) ""))
1782 ;          (not (file-directory-p (, makefile)))
1783 ;          (file-readable-p       (, makefile)))))
1784 (defun mc--makefile-test-p (makefile)
1785   (cond
1786    ((or (not makefile)
1787         (string-equal makefile ""))
1788     (mc--msg "Empty makefile selection")
1789     nil)
1790    ((file-directory-p makefile)
1791     (mc--msg "Makefile selection %s is a directory !!" makefile)
1792     nil)
1793    ((not (file-readable-p makefile))
1794     (mc--msg "Makefile %s unreadable" makefile)
1795     nil)
1796    (t)))
1797
1798
1799 (if (not (fboundp 'buffer-modified-tick))
1800     (fset 'buffer-modified-tick
1801           ;; allways indicate modified
1802           (function
1803            (lambda()
1804              (if mc--mkfl-buffer-tick
1805                  (+ mc--mkfl-buffer-tick 1)
1806                1)))))
1807
1808 (defun  mc--get-makefile-rules (makefile)
1809   ;; Try to find if makefile's buffer has been modified
1810   ;; since last rule extraction
1811   (if (or (not mc--mkfl-buffer-tick)
1812           (not (equal mc--mkfl-buffer-tick
1813                       (buffer-modified-tick))))
1814       (save-excursion
1815         (save-restriction
1816           (widen)
1817           (goto-char (point-min))
1818           (setq mc--mkfl-buffer-tick (buffer-modified-tick))
1819           (setq mc--makefile-rules   nil)
1820           (mc--msg "Extracting rules from %s ..." makefile)
1821           ;; Grep into tmp buffer for makefile rules
1822           (while (re-search-forward mc--makefile-rules-regexp nil t)
1823             (let ((rule (buffer-substring
1824                          (match-beginning 1)
1825                          (match-end       1))))
1826               ;; add rule to list if it don't match the ignore regexp
1827               ;; and if not allready in rules list.
1828               (if (and
1829                    (or (not mode-compile-ignore-makerule-regexp)
1830                        (not (string-match
1831                              mode-compile-ignore-makerule-regexp
1832                              rule)))
1833                    (not (mc--member rule mc--makefile-rules)))
1834                   (setq mc--makefile-rules
1835                         (append mc--makefile-rules
1836                                 (list rule))))))))
1837     (mc--msg "Rules had already been extracted from %s ..." makefile))
1838   ;; Always add an empty rule to allow `default' choice.
1839   (append mc--makefile-rules '([])))
1840
1841 (defun mc--makerule-completion (alist outfile &optional pref)
1842   ;; Return the makerule completion according to the prefered
1843   ;; default makerule
1844   (let ((preference (or pref
1845                         mode-compile-prefered-default-makerule)))
1846     (mc--msg "Prefered makerule choice is '%s" preference)
1847     (cond
1848      ((eq preference 'none)
1849       ;; Just show max common completion string to user
1850       (or (mc--common-completion alist) ""))
1851
1852      ((eq preference 'all)
1853       ;; Find the all rule or 'none
1854       (if (assoc "all" alist) "all"
1855         (mc--makerule-completion alist outfile 'none)))
1856
1857      ((eq preference 'file)
1858       ;; The out file is prefered or 'none
1859       (or outfile (mc--makerule-completion alist outfile 'none)))
1860
1861      ((eq preference 'default)
1862       ;; Find the default rule or ""
1863       (if (assoc "default" alist) "default" ""))
1864
1865      (t
1866       ;; Invalid preference return 'none
1867       (mc--msg "Invalid `mode-compile-prefered-default-makerule': '%s"
1868                mode-compile-prefered-default-makerule)
1869       (mc--makerule-completion alist outfile 'none)))))
1870
1871 (defun mc--choose-makefile-rule (makefile &optional outfile)
1872   ;; Choose the makefile rule and set it makefile local
1873   (save-excursion
1874     ;; Switch to makefile buffer
1875     (set-buffer (find-file-noselect makefile))
1876     (setq mc--selected-makerule
1877           ;; Add the name of the out file to the makefile
1878           ;; rules list if not allready in.
1879           (let* ((mk-rules-alist (mc--get-makefile-rules makefile))
1880                  (choices        (mapcar '(lambda (x) (list x))
1881                                          (if (or (not outfile)
1882                                                  (mc--member outfile
1883                                                              mk-rules-alist))
1884                                              mk-rules-alist
1885                                            (append mk-rules-alist
1886                                                    (list outfile))))))
1887             (completing-read
1888              (if mode-compile-expert-p
1889                  "Make rule: "
1890                "Using `make', enter rule to rebuild ([TAB] to complete): ")
1891              choices
1892              nil nil
1893              ;; initial contents
1894              (or mc--selected-makerule
1895                  (mc--makerule-completion choices outfile
1896                                           (if outfile 'file)))
1897              mc--selected-makerule-history
1898              )))))
1899
1900 (defmacro mc--cleanup-makefile-list (makefile-list)
1901   ;; Remove unusable and/or backups makefiles from list
1902   (` (let ((newlist))
1903        (mapcar
1904         '(lambda (x)
1905            (if (and (mc--makefile-test-p x)
1906                     (or (not mode-compile-ignore-makefile-backups)
1907                         (not (string-match
1908                               mode-compile-makefile-backups-regexp
1909                               x))))
1910                (setq newlist (cons x newlist))
1911              (mc--msg "Removing makefile \"%s\" from completion list"
1912                       x)))
1913         (, makefile-list))
1914        newlist)))
1915
1916 (defun mc--makefile-to-use (&optional directory)
1917   ;; Find the makefile to use in the current directory
1918   (let ((makefile-list (mc--cleanup-makefile-list
1919                         (directory-files
1920                          ;; I do not use the 5th parameter in Lucid Emacs
1921                          ;; to be compatible with GNU Emacs which accept
1922                          ;; only 4 parameters - no NOSORT -.
1923                          (or directory default-directory)
1924                          nil mode-compile-makefile-regexp t))))
1925     (cond
1926      ((not makefile-list)
1927       ;; No makefile found
1928       nil)
1929
1930      ((and (not (cdr-safe makefile-list))
1931            (mc--makefile-test-p (car makefile-list)))
1932       ;; Only one valid makefile
1933       (car makefile-list))
1934
1935      (t
1936       ;; Many makefiles in directory ask user to select one
1937       (let ((choices  (mapcar
1938                        '(lambda (x) (list x))
1939                        makefile-list))
1940             (makefile nil))
1941         (while
1942             ;; While the makefile do not pass the test.
1943             (not (mc--makefile-test-p
1944                   (setq makefile
1945                         (completing-read
1946                          (if mode-compile-expert-p
1947                              "Makefile: "
1948                            "Using `make', select makefile to use ([TAB] to complete): ")
1949                          choices
1950                          nil t
1951                          ;; initial contents
1952                          (or mc--selected-makefile
1953                              (mc--common-completion choices))
1954                          mc--selected-makefile-history
1955                          )))))
1956         makefile)))))
1957
1958 (defun mc--set-command (&optional file)
1959   ;; Return a compilation command, built according to the existence
1960   ;; of a makefile or not, to compile FILE .
1961   (setq completion-ignore-case nil) ; let completion be case sensitive
1962   (let ((to-compile-fname (or file (mc--find-to-compile-file))))
1963     (if (setq mc--selected-makefile (mc--makefile-to-use))
1964         (progn
1965           ;; A makefile found in the directory:
1966           ;; using make to compile
1967           (let ((out-fname (if to-compile-fname
1968                                (mc--guess-compile-result-fname
1969                                 to-compile-fname)
1970                              nil)))
1971             ;; build make command by asking rule to user
1972             (concat mode-compile-make-program " "
1973                     (or (mc--eval mode-compile-make-options) "")
1974                     " -f " mc--selected-makefile " "
1975                     (mc--choose-makefile-rule
1976                      mc--selected-makefile out-fname))))
1977       ;; else
1978       ;; No makefile: build compile command asking  for confirmation to user.
1979       ;; Should this be replaced by the creation of a makefile (and then
1980       ;; running it) as rms proposed me?
1981       (or mc--compile-command
1982           (setq mc--compile-command
1983                 (concat (setq mode-compile-choosen-compiler
1984                               (mc--find-compiler)) " "
1985                         (or (getenv mc--cflags-varenv)
1986                             (mc--eval mc--comp-options))
1987                         (if to-compile-fname
1988                             (if mc--build-op-args
1989                                 (mc--build-output-args to-compile-fname)
1990                               (concat " " to-compile-fname)
1991                               )
1992                           " "))))
1993       (if (not mode-compile-never-edit-command-p)
1994           (setq mc--compile-command
1995                 (mc--read-string
1996                  (if mode-compile-expert-p
1997                      "Compile command: "
1998                    (if to-compile-fname
1999                        (format "Edit command to compile %s: "
2000                                to-compile-fname)
2001                      "Edit compile command: " ))
2002                  mc--compile-command))
2003         mc--compile-command))))
2004
2005 (defun mc--shell-compile (shell dbgflags &optional errors-regexp-alist)
2006   ;; Run SHELL with debug flags DBGFLAGS on current-buffer
2007   (let* ((shcmd   (or (mc--which shell)
2008                       (error "Compilation abort: command %s not found" shell)))
2009          (shfile  (or mc--remote-pathname (buffer-file-name)
2010                       (error "Compilation abort: Buffer %s has no filename"
2011                              (buffer-name))))
2012          (run-cmd (concat shcmd " " dbgflags " " shfile " "
2013                           (setq mc--shell-args
2014                                 (read-string (if mode-compile-expert-p
2015                                                  "Argv: "
2016                                                (format "Arguments to %s %s script: "
2017                                                        shfile shell))
2018                                              mc--shell-args)))))
2019     ;; Modify compilation-error-regexp-alist if needed
2020     (if errors-regexp-alist
2021         (progn
2022           ;; Set compilation-error-regexp-alist from compile
2023           (or (listp errors-regexp-alist)
2024               (error "Compilation abort: In mc--shell-compile errors-regexp-alist not a list."))
2025           ;; Add new regexp alist to compilation-error-regexp-alist
2026           (mapcar '(lambda(x)
2027                      (if (mc--member x compilation-error-regexp-alist) nil
2028                        (setq compilation-error-regexp-alist
2029                              (append (list x)
2030                                      compilation-error-regexp-alist))))
2031                   errors-regexp-alist)))
2032     ;; Run compile with run-cmd
2033     (mc--compile run-cmd)))
2034
2035 (defmacro mc--assq-get-fcomp (asq)
2036   ;; Return compile-function associated to ASQ
2037   (` (let* ((mode  (cdr  (, asq)))
2038             (massq (assq mode mode-compile-modes-alist)))
2039        (if massq (car-safe (cdr massq))))))
2040
2041 (defmacro mc--assq-get-fkill (asq)
2042   ;; Return kill-compile-function associated to ASQ
2043   (` (let* ((mode  (cdr  (, asq)))
2044             (massq (assq mode mode-compile-modes-alist)))
2045        (if massq (car-safe (cdr-safe (cdr massq)))))))
2046
2047 (defun mc--lookin-for-shell ()
2048   ;; Look into current-buffer to see if it is a shell script
2049   ;; and return function to compile it or nil.
2050   (mc--msg "Looking if buffer %s is a shell script..." (buffer-name))
2051   (save-excursion
2052     (save-restriction
2053       (widen)
2054       (goto-char (point-min))
2055       (if (looking-at "#![ \t]*/\\([^ \t\n]+/\\)\\([^ \t\n]+\\)")
2056           (let* ((shell-name (buffer-substring (match-beginning 2)
2057                                                (match-end       2)))
2058                  (shell-assq (assoc shell-name mode-compile-shell-alist)))
2059             (if shell-assq
2060                 (progn
2061                   (mc--msg "Buffer is a %s script" shell-name)
2062                   (setq mc--kill-compile (mc--assq-get-fkill shell-assq))
2063                   (mc--assq-get-fcomp shell-assq))
2064               nil))))))
2065
2066 (defun mc--lookat-name ()
2067   ;; Lookat buffer file name to see if it can return a function
2068   ;; to compile it or nil.
2069   (mc--msg "Trying to guess compile command from buffer %s file name..."
2070            (buffer-name))
2071   (let ((fname (buffer-file-name)))
2072     (if (not fname) nil
2073       ;; try regexp from mode-compile-filename-regexp-alist
2074       (let ((tmp-al mode-compile-filename-regexp-alist)
2075             (found  nil))
2076         (while (and tmp-al (car tmp-al) (not found))
2077           ;; evaluate to string
2078           (let ((regxp (mc--eval (car (car tmp-al)))))
2079             (if (string-match regxp fname)
2080                 (setq found (car tmp-al)))
2081             (setq tmp-al (cdr tmp-al))))
2082         (if (not found)
2083             nil
2084           (mc--msg "File %s matches regexp %s" fname (car found))
2085           (setq mc--kill-compile (mc--assq-get-fkill found))
2086           (mc--assq-get-fcomp found))))))
2087 \f
2088
2089 ;; @ mode specific functions ;;;
2090
2091 (defun cc-compile ()
2092   "Run `compile' with a dynamically built command for `c-mode'.
2093
2094 The command is built depending of the existence of a makefile (which could
2095 be specified by changing value of variable mode-compile-makefile-regexp) in
2096 the current directory or not.
2097 If no makefile is found try to run a C compiler on the file or it's companion.
2098
2099 See also variables:
2100  -- cc-compilers-list
2101  -- cc-default-compiler
2102  -- cc-companion-file-regexp
2103  -- cc-compiler-varenv
2104  -- cc-cflags-varenv
2105  -- cc-source-ext-list
2106  -- cc-headers-ext-list
2107  -- cc-source-file-ext-regexp"
2108   (setq
2109    mc--comp-lst          cc-compilers-list
2110    mc--def-comp          cc-default-compiler
2111    mc--compfile-regexp   cc-companion-file-regexp
2112    mc--comp-varenv       cc-compiler-varenv
2113    mc--comp-options      cc-default-compiler-options
2114    mc--cflags-varenv     cc-cflags-varenv
2115    mc--source-ext-lst    cc-source-ext-list
2116    mc--head-ext-lst      cc-headers-ext-list
2117    mc--source-ext-regexp cc-source-file-ext-regexp
2118    mc--build-op-args     cc-build-output-args
2119    mc--outfile-ext       cc-object-file-ext
2120    )
2121   (mc--compile (mc--set-command)))
2122
2123 (defun java-compile ()
2124   "Run `compile' with a dynamically built command for `java-mode'.
2125
2126 The command is built depending of the existence of a makefile (which could
2127 be specified by changing value of variable mode-compile-makefile-regexp) in
2128 the current directory or not.
2129 If no makefile is found try to run a Java compiler on the file or it's
2130 companion.
2131
2132 See also variables:
2133  -- java-compilers-list
2134  -- java-default-compiler
2135  -- java-companion-file-regexp
2136  -- java-compiler-varenv
2137  -- java-cflags-varenv
2138  -- java-source-ext-list
2139  -- java-headers-ext-list
2140  -- java-source-file-ext-regexp"
2141   (setq
2142    mc--comp-lst          java-compilers-list
2143    mc--def-comp          java-default-compiler
2144    mc--compfile-regexp   java-companion-file-regexp
2145    mc--comp-varenv       java-compiler-varenv
2146    mc--comp-options      java-default-compiler-options
2147    mc--cflags-varenv     java-cflags-varenv
2148    mc--source-ext-lst    java-source-ext-list
2149    mc--head-ext-lst      java-headers-ext-list
2150    mc--source-ext-regexp java-source-file-ext-regexp
2151    mc--build-op-args     java-build-output-args
2152    mc--outfile-ext       java-object-file-ext
2153    )
2154   (mc--compile (mc--set-command)))
2155
2156 (defun c++-compile ()
2157   "Run `compile' with a dynamically built command for `c++-mode'.
2158
2159 The command is built depending of the existence of a makefile (which could
2160 be specified by changing value of variable mode-compile-makefile-regexp) in
2161 the current directory or not.
2162 If no makefile is found try to run a C++ compiler on the file or it's companion.
2163
2164 See also variables:
2165  -- c++-compilers-list
2166  -- c++-default-compiler
2167  -- c++-companion-file-regexp
2168  -- c++-compiler-varenv
2169  -- c++-cflags-varenv
2170  -- c++-source-ext-list
2171  -- c++-headers-ext-list
2172  -- c++-source-file-ext-regexp"
2173   (setq
2174    mc--comp-lst          c++-compilers-list
2175    mc--def-comp          c++-default-compiler
2176    mc--compfile-regexp   c++-companion-file-regexp
2177    mc--comp-varenv       c++-compiler-varenv
2178    mc--comp-options      c++-default-compiler-options
2179    mc--cflags-varenv     c++-cflags-varenv
2180    mc--source-ext-lst    c++-source-ext-list
2181    mc--head-ext-lst      c++-headers-ext-list
2182    mc--source-ext-regexp c++-source-file-ext-regexp
2183    mc--build-op-args     c++-build-output-args
2184    mc--outfile-ext       c++-object-file-ext
2185    )
2186   (mc--compile (mc--set-command)))
2187
2188
2189 (defun ada-compile ()
2190   "Run `compile' with a dynamically built command for `ada-mode'.
2191
2192 The command is built depending of the existence of a makefile (which could
2193 be specified by changing value of variable mode-compile-makefile-regexp) in
2194 the current directory or not.
2195 If no makefile is found try to run an Ada compiler on the file.
2196
2197 See also variables:
2198  -- ada-compilers-list
2199  -- ada-default-compiler
2200  -- ada-companion-file-regexp
2201  -- ada-compiler-varenv
2202  -- ada-aflags-varenv
2203  -- ada-source-ext-list
2204  -- ada-headers-ext-list
2205  -- ada-source-file-ext-regexp)"
2206   (setq
2207    mc--comp-lst          ada-compilers-list
2208    mc--def-comp          ada-default-compiler
2209    mc--compfile-regexp   ada-companion-file-regexp
2210    mc--comp-varenv       ada-compiler-varenv
2211    mc--comp-options      ada-default-compiler-options
2212    mc--cflags-varenv     ada-aflags-varenv
2213    mc--source-ext-lst    ada-source-ext-list
2214    mc--head-ext-lst      ada-headers-ext-list
2215    mc--source-ext-regexp ada-source-file-ext-regexp
2216    mc--build-op-args     ada-build-output-args
2217    mc--outfile-ext       ada-object-file-ext
2218    )
2219   (mc--compile (mc--set-command)))
2220
2221
2222 (defun f77-compile ()
2223   "Run `compile' with a dynamically built command for `fortran-mode'.
2224
2225 The command is built depending of the existence of a makefile (which could
2226 be specified by changing value of variable mode-compile-makefile-regexp) in
2227 the current directory or not.
2228 If no makefile is found try to run a Fortran compiler on the file or it's companion..
2229
2230 See also variables:
2231  -- f77-compilers-list
2232  -- f77-default-compiler
2233  -- f77-companion-file-regexp
2234  -- f77-compiler-varenv
2235  -- f77-cflags-varenv
2236  -- f77-source-ext-list
2237  -- f77-headers-ext-list
2238  -- f77-source-file-ext-regexp)"
2239   (setq
2240    mc--comp-lst          f77-compilers-list
2241    mc--def-comp          f77-default-compiler
2242    mc--compfile-regexp   f77-companion-file-regexp
2243    mc--comp-varenv       f77-compiler-varenv
2244    mc--cflags-varenv     f77-cflags-varenv
2245    mc--comp-options      f77-default-compiler-options
2246    mc--source-ext-lst    f77-source-ext-list
2247    mc--head-ext-lst      f77-headers-ext-list
2248    mc--source-ext-regexp f77-source-file-ext-regexp
2249    mc--build-op-args     f77-build-output-args
2250    mc--outfile-ext       f77-object-file-ext
2251    )
2252   (mc--compile (mc--set-command)))
2253
2254
2255 (defun elisp-compile ()
2256   "Run `byte-compile' on the current Emacs lisp buffer.
2257 For `emacs-lisp-mode' and `lisp-interaction-mode'.
2258
2259 Produce a `.elc' file if possible or `byte-compile' only the buffer."
2260   (let ((comp-file (or (buffer-file-name) "")))
2261     (if (string-match emacs-lisp-sources-regexp comp-file)
2262         (progn
2263           (mc--msg "Byte compiling file %s ..." comp-file)
2264           (byte-compile-file comp-file))
2265       (mc--msg "Byte compiling buffer %s #No .elc produced ..." (buffer-name))
2266       (mc--byte-compile-buffer))))
2267
2268
2269 (defun makefile-compile (&optional makefile)
2270   "Run `make' on the current-buffer (`makefile-mode').
2271
2272 The user is prompted for a selection of make rules to build."
2273   (let ((mkfile (or makefile (buffer-file-name)
2274                     (error
2275                      "Compilation abort: buffer %s has no file name"
2276                      (buffer-name)))))
2277     (setq mc--selected-makefile mkfile)
2278     (setq mc--compile-command
2279           (concat mode-compile-make-program " "
2280                   (or (mc--eval mode-compile-make-options) "")
2281                   " -f " mkfile " "
2282                   (mc--choose-makefile-rule mkfile))))
2283     (mc--compile mc--compile-command))
2284
2285
2286 (defun dired-compile ()
2287   "Run `make' if a Makefile is present in current directory (`dired-mode').
2288
2289 The user is prompted for a selection of a makefile to choose if many
2290 matching `mode-compile-makefile-regexp' are present in the directory and
2291 for the make rules to build. If directory contain no makefile the function
2292 try to find if there are some un-byte-compiled .el files and recompile them
2293 if needed.
2294 Ask for the complete `compile-command' if no makefile and no .el files found."
2295   (let ((makefile (mc--makefile-to-use)))
2296     (if makefile
2297         ;; Makefile exists compile with it
2298         (makefile-compile makefile)
2299       ;; No makefile found look for some .el files
2300       (mc--msg "No makefile found, looking for .el files ...")
2301       (let ((el-files (directory-files
2302                        default-directory nil emacs-lisp-sources-regexp)))
2303         (if el-files
2304             ;; Some .el files found byte-recompile them
2305             (mc--byte-recompile-files el-files)
2306           ;; No .el files ask compile command to user
2307           (mc--msg "No .el files found in directory %s" default-directory)
2308           (default-compile))))))
2309
2310
2311 (defun sh-compile ()
2312   "Run `sh-command' (Bourne Shell) with `sh-dbg-flags' on current-buffer (`sh-mode').
2313
2314 User is prompted for arguments to run his sh program with.
2315 If you want to step throught errors set the variable `sh-compilation-error-regexp-alist'
2316 to a value understandable by compile's `next-error'.
2317 See variables compilation-error-regexp-alist or sh-compilation-error-regexp-alist."
2318   (mc--shell-compile sh-command sh-dbg-flags sh-compilation-error-regexp-alist))
2319
2320
2321 (defun csh-compile ()
2322   "Run `csh-command' (C Shell) with `csh-dbg-flags' on current-buffer (`csh-mode').
2323
2324 User is prompted for arguments to run his csh program with.
2325 If you want to step throught errors set the variable `csh-compilation-error-regexp-alist'
2326 to a value understandable by compile's `next-error'.
2327 See variables compilation-error-regexp-alist or csh-compilation-error-regexp-alist."
2328   (mc--shell-compile csh-command csh-dbg-flags csh-compilation-error-regexp-alist))
2329
2330
2331 (defun zsh-compile ()
2332   "Run `zsh-command' (Z Shell) with `zsh-dbg-flags' on current-buffer (`zsh-mode').
2333
2334 User is prompted for arguments to run his zsh program with.
2335 If you want to step throught errors set the variable `zsh-compilation-error-regexp-alist'
2336 to a value understandable by compile's `next-error'.
2337 See variables compilation-error-regexp-alist or zsh-compilation-error-regexp-alist."
2338   (mc--shell-compile zsh-command zsh-dbg-flags zsh-compilation-error-regexp-alist))
2339
2340
2341 (defun perl-compile ()
2342   "Run Perl with `perl-dbg-flags' on current-buffer (`perl-mode').
2343
2344 User is prompted for arguments to run his perl program with.
2345 If you want to step throught errors set the variable `perl-compilation-error-regexp-alist'
2346 to a value understandable by compile's `next-error'.
2347 See variables compilation-error-regexp-alist or perl-compilation-error-regexp-alist."
2348   (mc--shell-compile perl-command perl-dbg-flags perl-compilation-error-regexp-alist))
2349
2350
2351 (defun tcl-compile ()
2352   ;; JWH
2353   "Run `tcl-command' with `tcl-dbg-flags' on current-buffer (`tcl-mode').
2354
2355 User is prompted for arguments to run his Tcl/Tk program with.
2356 If you want to step throught errors set the variable `tcl-compilation-error-regexp-alist'
2357 to a value understandable by compile's `next-error'.
2358 See variables compilation-error-regexp-alist or tcl-compilation-error-regexp-alist."
2359   (mc--shell-compile tcl-command tcl-dbg-flags tcl-compilation-error-regexp-alist))
2360
2361
2362 (defun python-compile ()
2363   ;; BM
2364   "Run `python-command' with `python-dbg-flags' on current-buffer (`python-mode').
2365
2366 User is prompted for arguments to run his Python program with.
2367 If you want to step throught errors set the variable `python-compilation-error-regexp-alist'
2368 to a value understandable by compile's `next-error'.
2369 See variables compilation-error-regexp-alist or python-compilation-error-regexp-alist."
2370   (mc--shell-compile python-command python-dbg-flags python-compilation-error-regexp-alist))
2371
2372
2373 (defun default-compile ()
2374   "Default function invoked by `mode-compile' (\\[mode-compile])
2375 when everything else failed.
2376
2377 Ask to user to edit `compile-command' and run `compile' (\\[compile]) with it."
2378   (setq mc--compile-command
2379         (mc--read-string
2380          (if mode-compile-expert-p
2381              "Compile command: "
2382            (format "Edit command to compile %s : " (buffer-name)))
2383          (or mc--compile-command compile-command)))
2384   (mc--compile mc--compile-command))
2385
2386 (defvar mc--makefile) ;; Just to avoid compiler warning
2387 (defun guess-compile ()
2388   "Try to guess how to compile current-buffer.
2389
2390 When the compile command could not be extrapolated from major-mode this function
2391 is called which try to guess from number of parameters which command to build.
2392 The steps to guess which command to use to compile are:
2393   1st : Look into the file to check if it is a shell script
2394         See variable mode-compile-shell-alist
2395   2nd : Try to guess from the file name
2396         See variable mode-compile-filename-regexp-alist
2397   3rd : Look for a makefile in the current directory
2398         See variable mode-compile-makefile-regexp
2399   Last: Give up and ask user for the command to use
2400         See function default-compile"
2401   (mc--msg "Trying to guess how to compile buffer %s ..." (buffer-name))
2402   (let ((mc--makefile))
2403     (funcall
2404      (or
2405       ;; step 1
2406       (mc--lookin-for-shell)
2407       ;; step 2
2408       (mc--lookat-name)
2409       ;; step 3
2410       (progn
2411         (mc--msg "Looking for a makefile in current directory...")
2412         (if (setq mc--makefile (mc--makefile-to-use
2413                                 (and (buffer-file-name)
2414                                      (file-name-directory (buffer-file-name)))))
2415             (progn
2416               (setq mc--kill-compile 'kill-compilation)
2417               ;; Byte-compiling says `makefile' is not referenced.
2418               '(lambda () (makefile-compile mc--makefile)))))
2419       ;; step 4
2420       (progn
2421         (mc--msg "Don't know how to compile %s, giving up..."
2422                  (buffer-name))
2423         (setq mc--kill-compile 'kill-compilation)
2424         'default-compile)))))
2425 \f
2426
2427 ;; @ user accessible/exported function ;;;
2428
2429 ;; get reporter-submit-bug-report when byte-compiling
2430 (and (fboundp 'eval-when-compile)
2431      (eval-when-compile (require 'reporter)))
2432
2433 ;;;###autoload
2434 (defun mode-compile-submit-bug-report ()
2435   "*Submit via mail a bug report on mode-compile v2.27."
2436   (interactive)
2437   (and
2438    (y-or-n-p "Do you REALLY want to submit a report on mode-compile? ")
2439    (require 'reporter)
2440    (reporter-submit-bug-report
2441     mode-compile-help-address
2442     (concat "mode-compile " mode-compile-version)
2443     (list
2444      ;; Interesting mode-compile variables
2445      'mode-compile-modes-alist
2446      'mode-compile-filename-regexp-alist
2447      'mode-compile-shell-alist
2448      'mode-compile-makefile-regexp
2449      'mode-compile-make-program
2450      'mode-compile-default-make-options
2451      'mode-compile-make-options
2452      'mode-compile-reading-time
2453      'mode-compile-expert-p
2454      'mode-compile-never-edit-command-p
2455      'mode-compile-save-all-p
2456      'mode-compile-always-save-buffer-p
2457      'mode-compile-before-compile-hook
2458      'mode-compile-after-compile-hook
2459      'mode-compile-before-kill-hook
2460      'mode-compile-after-kill-hook
2461      'mode-compile-other-frame-p
2462      'mode-compile-other-frame-name
2463      'mode-compile-frame-parameters-alist
2464      'mode-compile-prefered-default-makerule
2465      'emacs-lisp-byte-compile-dir-interactive-p
2466      ;; others variables
2467      'features
2468      'compilation-error-regexp-alist
2469      'compile-command
2470      )
2471     nil
2472     nil
2473     "Dear Heddy,")))
2474 \f
2475
2476 ;;;###autoload
2477 (defun mode-compile (&optional remote-host)
2478   "*Compile the file in the current buffer with a dynamically built command.
2479
2480 The command is built according to the current major mode the function
2481 was invoked from.
2482
2483 Running this command preceded by universal-argument (\\[universal-argument])
2484 allows remote compilation, the user is prompted for a host name to run the
2485 compilation command on.
2486
2487 Currently know how to compile in:
2488  `c-mode' ,              -- function cc-compile.
2489  `java-mode' ,           -- function java-compile.
2490  `c++-mode',             -- function c++-compile.
2491  `ada-mode',             -- function ada-compile.
2492  `fortran-mode',         -- function f77-compile.
2493  `emacs-lisp-mode'       -- function elisp-compile.
2494  `lisp-interaction-mode' -- function elisp-compile.
2495  `makefile-mode'         -- function makefile-compile.
2496  `dired-mode'            -- function dired-compile.
2497  `sh-mode'               -- function sh-compile.
2498  `csh-mode'              -- function csh-compile.
2499  `zsh-mode'              -- function zsh-compile.
2500  `perl-mode'             -- function perl-compile.
2501  `cperl-mode'            -- function perl-compile.
2502  `tcl-mode'              -- function tcl-compile.
2503  `python-mode'           -- function python-compile.
2504  `fundamental-mode'      -- function guess-compile.
2505  `text-mode'             -- function guess-compile.
2506  `indented-text-mode'    -- function guess-compile.
2507  `compilation-mode'      -- function default-compile.
2508  The function `guess-compile' is called when mode is unknown.
2509
2510 The variable `mode-compile-modes-alist' contain description of known
2511 modes.  The hooks variables `mode-compile-before-compile-hook' and
2512 `mode-compile-after-compile-hook' are run just before and after
2513 invoking the compile command of the mode.
2514
2515 Use the command `mode-compile-kill' (\\[mode-compile-kill]) to abort a
2516 running compilation.
2517
2518 Bound on \\[mode-compile]."
2519   (interactive "P")
2520   ;; reinit
2521   (setq
2522    mc--efs-path-list  nil
2523    mc--remote-command nil)
2524   (if remote-host
2525       ;; Remote compilation asked
2526       ;; prepare remote command
2527       (mc--set-remote-cmd remote-host)
2528     ;; Not asked but check buffer-file-name to see
2529     ;; if it is not an efs file
2530     (setq mc--efs-path-list (and (fboundp 'efs-ftp-path)
2531                                  (buffer-file-name)
2532                                  (efs-ftp-path (buffer-file-name))))
2533     (and mc--efs-path-list (mc--set-remote-cmd
2534                             (car mc--efs-path-list)
2535                             (nth 1 mc--efs-path-list)
2536                             (nth 2 mc--efs-path-list))))
2537   (if (and mode-compile-always-save-buffer-p
2538            (buffer-file-name))
2539       ;; save-buffer allready check if buffer had been modified
2540       (save-buffer))
2541   (if mode-compile-save-all-p (save-some-buffers t))
2542   ;; Check if compile-command set as local variable
2543   (if (and
2544        (boundp 'compile-command)
2545        (local-variable-p 'compile-command (current-buffer))
2546        compile-command ; not null
2547        (if mc--compile-command
2548            (equal compile-command mc--compile-command)
2549          t)
2550        )
2551       ;; Just ask user and go
2552       (progn
2553         (mc--run-hooks 'mode-compile-before-compile-hook)
2554         (default-compile)
2555         (mc--run-hooks 'mode-compile-after-compile-hook)
2556         )
2557     ;; Here is the real work
2558     (let ((mode-elem (assq major-mode mode-compile-modes-alist)))
2559       (if mode-elem
2560           ;; known mode
2561           (progn
2562             (mc--msg (substitute-command-keys
2563                       "Compiling in %s mode ... \\[mode-compile-kill] to kill.")
2564                      mode-name)
2565             (mc--run-hooks 'mode-compile-before-compile-hook)
2566             ;; mc--funcall can launch the compilation
2567             ;; in another frame.
2568             (mc--funcall   (car (cdr mode-elem)))
2569             (mc--run-hooks 'mode-compile-after-compile-hook))
2570         ;; unknown mode: try to guess
2571         (mc--msg (substitute-command-keys
2572                   "Don't know how to compile in %s mode, guessing... \\[mode-compile-kill] to kill.")
2573                  mode-name)
2574         (mc--run-hooks 'mode-compile-before-compile-hook)
2575         ;; mc--funcall can launch the compilation
2576         ;; in another frame.
2577         (mc--funcall   'guess-compile)
2578         (mc--run-hooks 'mode-compile-after-compile-hook)))))
2579
2580 (provide 'mode-compile)
2581 \f
2582
2583 ;;;###autoload
2584 (defun mode-compile-kill()
2585   "*Kill the running compilation launched by `mode-compile' (\\[mode-compile]) \
2586 command.
2587
2588 The compilation command is killed according to the current major mode
2589 the function was invoked from.
2590
2591 Currently know how to kill compilations from:
2592  `c-mode' ,              -- function kill-compilation.
2593  `java-mode' ,           -- function kill-compilation.
2594  `c++-mode' ,            -- function kill-compilation.
2595  `ada-mode' ,            -- function kill-compilation.
2596  `fortran-mode' ,        -- function kill-compilation.
2597  `emacs-lisp-mode'       -- function keyboard-quit.
2598  `lisp-interaction-mode' -- function keyboard-quit.
2599  `makefile-mode'         -- function kill-compilation.
2600  `dired-mode'            -- function kill-compilation.
2601  `sh-mode'               -- function kill-compilation.
2602  `csh-mode'              -- function kill-compilation.
2603  `zsh-mode'              -- function kill-compilation.
2604  `perl-mode'             -- function kill-compilation.
2605  `cperl-mode'            -- function kill-compilation.
2606  `tcl-mode'              -- function kill-compilation.
2607  `python-mode'           -- function kill-compilation.
2608  `fundamental-mode'      -- Bound dynamically.
2609  `text-mode'             -- Bound dynamically.
2610  `indented-text-mode'    -- Bound dynamically.
2611  `compilation-mode'      -- function kill-compilation.
2612
2613 The variable `mode-compile-modes-alist' contain description of ALL
2614 known modes.  The hooks variables `mode-compile-before-kill-hook' and
2615 `mode-compile-after-kill-hook' are run just before and after invoking
2616 the kill compile command of the mode.
2617
2618 Bound on \\[mode-compile-kill]."
2619   (interactive)
2620   (let ((mode-elem (assq major-mode mode-compile-modes-alist)))
2621     (if mode-elem
2622         ;; known mode
2623         (progn
2624           (mc--run-hooks 'mode-compile-before-kill-hook)
2625           (mc--msg "Killing compilation in %s mode..." mode-name)
2626           (let ((killfun (or (car-safe (cdr (cdr mode-elem)))
2627                              mc--kill-compile
2628                              nil)))
2629             (if killfun
2630                 ;; I don't call mc--funcall here caus' we don't need
2631                 ;; to switch to another frame to kill a compilation.
2632                 (funcall killfun)
2633               (mc--msg "Unable to kill compilation in %s mode..." mode-name))
2634             (mc--run-hooks 'mode-compile-after-kill-hook)))
2635       ;; unknown mode
2636       (mc--msg "Don't know how to kill compilation in %s mode"
2637                mode-name))))
2638
2639 (provide 'mode-compile-kill)
2640
2641 \f
2642
2643 ;;; Local variables:
2644 ;;; outline-regexp: ";; @+"
2645 ;;; eval: (outline-minor-mode 1)
2646 ;;; End:
2647
2648 ;;; mode-compile.el ends here