Author: Heddy Boubaker
Updated:
Compile files according to major-mode
This package needs a new maintainer. Please contact the original author if you are interested. @ Purpose: ========== Provide `mode-compile' function as a replacement for the use of `compile' command which is very dumb for creating it's compilation command (use "make -k" by default). `mode-compile' is a layer above `compile'; Its purpose is mainly to build a smart compile-command for `compile' to execute it. This compile-command is built according to number of parameters: - the major-mode. - presence or not of a makefile in current directory. - the buffer-file-name and extension. - what is in the current buffer (`main' function,"#!/path/shell", ...). - and more ... (see Commentary section below). Most of these parameters are higly customizable throught Emacs Lisp variables (to be set in your .emacs or through Customization menu). Running mode-compile after an universal-argument (C-u) allows remote compilations, user is prompted for a host name to run the compilation command on. Another function provided is `mode-compile-kill' which terminate a running compilation session launched by `mode-compile'. @ Installation: =============== Byte compile this file (*) somewhere in your `load-path' and add in your .emacs: (autoload 'mode-compile "mode-compile" "Command to compile current buffer file based on the major mode" t) (global-set-key "\C-cc" 'mode-compile) (autoload 'mode-compile-kill "mode-compile" "Command to kill a compilation launched by `mode-compile'" t) (global-set-key "\C-ck" 'mode-compile-kill) By default mode-compile is very verbose and waits a few seconds (1 by default) after each message for the user to have time to read it. You could set variables `mode-compile-expert-p' and `mode-compile-reading-time' to change this behaviour. On X-Windows systems setting the variable `mode-compile-other-frame-p' will create a new frame and launch the compilation command in it. (*) Don't take care of messages: ** reference to free variable efs-remote-shell-file-name This is perfectly normal ;-}. But if you know a way to avoid it let me know. @ Documentation: ================ This section will explain how the `compile-command' are built according to the `major-mode' and how to customize it. The major modes `mode-compile' currently known are: - c-mode, c++-mode, makefile-mode, dired-mode, ada-mode, emacs-lisp-mode, lisp-interaction-mode, sh-mode, csh-mode, fundamental-mode, text-mode, indented-text-mode compilation-mode, fortran-mode, c?perl-mode, zsh-mode java-mode, tcl-mode, python-mode, ruby-mode For other modes a default behaviour is provided. When running `mode-compile' or `mode-compile-kill' the hooks `mode-compile-(before|after)-(compile|kill)-hook' are executed. The current buffer could be automaticaly saved if variable `mode-compile-always-save-buffer-p' is set to `t'. ALL the modified buffers could be automaticaly saved if variable `mode-compile-save-all-p' is set to `t'. @@ fundamental-mode, text-mode, indented-text-mode & UNKNOWN MODES: *** THIS IS TOO THE DEFAULT BEHAVIOR FOR UNKNOWN MODES *** Try to guess what the file is by: - 1st looking at it's name and extension (see variable `mode-compile-filename-regexp-alist'). - 2nd looking at string "#!/path/shell" at first line to extract shell to run the script with (see variable `mode-compile-shell-alist'). - 3rd looking at a makefile in current directory. - then calling `compile' with the last compile command which is asked to be edited by user ... The `kill-compile' command is then bound dynamically (buffer-local). @@ compilation-mode: Call `compile' with the last compile command. @@ makefile-mode: The makefile is run with make throught `compile' (user is prompted for the rule to run, see variable `mode-compile-prefered-default-makerule' to see how a default choice could be selected). @@ emacs-lisp-mode, lisp-interaction-mode: If the buffer is a .el file byte-compile it to produce a .elc file, else just byte-compile the buffer (this don't use `compile' but `byte-compile'). @@ dired-mode: Find a makefile in the directory and run make with it (like in makefile-mode), else try to byte-recompile all .el files olders than their associated .elc files (unlike `byte-recompile-directory' this is not recursive), finally if no .el files are present ask compilation command to user by calling `default-compile'. To find a makefile a regexp is provided which name is `mode-compile-makefile-regexp'. @@ sh-mode, csh-mode, zsh-mode: Run "[cz]?sh" with debugging arguments as specified in `[cz]?sh-dbg-flags' on the currently edited file. @@ c?perl-mode: Run file with "perl -w" (can step throught errors with compile's `next-error' command). @@ tcl-mode: Run file with "wish" (can step throught errors with compile's `next-error' command). @@ c-mode, c++-mode: First it try to see if there is a makefile in the directory, makefiles to look for are specified by the variable `mode-compile-makefile-regexp'. If yes two cases could happen: there is only one makefile so use it, or there is more than one (sometimes when you need to write portable soft you could have some makefiles by system: SunOs.make, HP.make ...), in that case prompt to user for choice (with smart completion). Once the makefile has been selected it extract the rules from it and ask to user to choose a rule to make (with smart completion, see variable `mode-compile-prefered- default-makerule' to see how a default choice could be selected). There are some cases where no makefiles are presents (YES I KNOW this is bad practice but you sometimes have no needs to write a Makefile). In that case the function try to build the most intelligent compilation command by using the favourite user C/C++ compiler: value of environment variable "CC" or "CXX" or first found, in the PATH, of compilers specified in variable `cc-compilers-list' or `c++-compilers-list'. Then it look for the varenv "CFLAGS" of "CXXFLAGS" to append to the compiler command, find the file to compile:.(c|cc|C|cpp) (see *) and ask for confirmation. If you really trust mode-compile will build the right command and want to bypass confirmation you could set the variable `mode-compile-never-edit-command-p' to t. (*) How to find : In both case the command try to guess which file has to be compiled: It's a trivial choice when current buffer file is a .(c|C|cc|cpp... -any file with extension specified in `cc-source-file-ext-list' or `c++-source-file-ext-list') file but when it's a .(h|H|hh) file what to do? The variable `cc-companion-file-regexp' or `c++-companion-file-regexp' specify how to find a .(c|C|cc|cpp...) file from a .(h|H|hh...); This is done by appending .(c|C|cc|cpp) to . In c-mode with default value it produce: file.h, file_[Pp].h -> file.c I sometimes use files _p.h to indicate that the file is a private header file for a .c file. In c++-mode with default value it produce: file.hh, file_[Pp].hh -> file.cc I sometimes use files _p.cc to indicate that the file is a private header file for a .cc file. The output of compilation will be a .o file if no `main' function is found inside or a EXECUTABLE file if `main' function found. @@ ada-mode: Same as c/c++-mode but run Ada compiler on the Ada file. There are no companion file and no way to find a main function in Ada. @@ fortran-mode: Same as c-mode but run Fortran compiler on .[Ff](or)? files. @@ java-mode: Same as c-mode but call "javac" without the -o option on .java files @@ python-mode: Run file with "python" (can step throught errors with compile's `next-error' command). @@ ruby-mode: Run file with "ruby" (can step throught errors with compile's `next-error' command). @@ message-mode: Run `message-send'. @ Contributors/Helpers: ======================= Adrian Aichner Bin Mu Charles L.G. Comstock Christian Motschke Edward Hartnett Gael MARZIOU Hartmut MANZ Henry Guillaume Ian Young Ilya Zakharevich John W. Harwell Kevin Broadey Lawrence R. Dodd Martin Jost Michael Welsh Duggan Rolf EBERT Scott Hofmann Stefan Schoef William A. Perkins boris @ ToDo: ======= Find a new maintainer. Extending this to some others programming languages (modes). Writting an Info documentation. Contributors are greatly accepted (send me diffs and don't forget to update documentation and all comments too please). Maybe Using ange-ftp parse .netrc utilities for remote host and user infos.