Finding the buffer file name in Emacs when compiling - emacs

I am trying to set up Emacs so that when I choose "Compile.." in the menu, Emacs executes "make filename" on the command line. I am trying something like:
(setq compile-command (concat "make " (file-name-sans-extension
buffer-file-name)))
but it doesn't work - it looks like Emacs is is looking for a file-name for the *scratch* buffer, which doesn't have one. Does anyone know how to fix this?
Thanks.
UPDATE: as suggested by Cheeso, a hook fixes the problem. Here is a version that works for me:
(defun cur-file ()
(file-name-sans-extension
(file-name-nondirectory (buffer-file-name (current-buffer)))))
(add-hook 'c++-mode-hook
(lambda()
(set (make-local-variable 'compile-command)
(concat "make " (cur-file)))))

Yes - a couple options for you.
Simple: define a file-local variable. In the header comment of your file just include something like
// -*- compile-command: "gcc -Wall -O3 -o f file.c" -*-
For more details, see:
https://stackoverflow.com/a/4540977/48082
More elaborate - there is a module called smarter-compile.el available on the marmalade repo. It allows you to define some rules for guessing the compile-command to use for a particular buffer. Like, if there's a makefile, use MAKE; otherwise, if the file is a .c file, use gcc; etc.
This is nice if you don't want to insert comments into every file, or if you have a myriad of different kinds of files and projects that you work on.
ps: the reason your simple setq isn't working, I'd guess, is that you are not evaluating it in the buffer that is being edited. Probably you want to put that into your personal xxxx-mode-hook-fn, where xxx is the mode of the file you are editing.

Related

Let .emacs.d behaves just like a .d folder

I want to solve my “.emacs bankruptcy” issue, and I've gone through
https://help.ubuntu.com/community/EmacsHowto
http://www.emacswiki.org/emacs/DotEmacsBankruptcy
http://www.emacswiki.org/emacs/DotEmacsDotD
http://www.gnu.org/software/emacs/manual/html_node/emacs/Init-File.html
and it is still unclear to me whether the .emacs.d folder is the solution. I.e., whether it will behave just like a normal .d folder, e.g., /etc/profile.d/, where you drop you scripts and they will be picked up by the system auto-magically. Please confirm.
If not, can someone give me a script that does that, or give me a solution please?
Thanks
The essential content of my ~/.emacs file is:
(require 'cl)
(loop for src in (directory-files "~/.emacs.d" 'full-path "[0-9].*\\.el$") do
(let ((byte (concat src "c")))
(when (file-newer-than-file-p src byte)
(byte-compile-file src))
(message "Loading %s.elc" byte)
(load-file byte)))
It loads configuration files from ~/.emacs.d which start with a number. If the source file (extension .el) is newer than the byte-compiled version (extension .elc) then it byte-compiles the source. Afterwards it loads the byte compiled file.
Here's my ~/.emacs:
;; base dirs
(defvar dropbox.d "~/Dropbox/")
(defvar emacs.d (concat dropbox.d "source/site-lisp/"))
;; load path
(add-to-list 'load-path emacs.d)
(defun add-subdirs-to-load-path (dir)
(let ((default-directory dir))
(normal-top-level-add-subdirs-to-load-path)))
(add-subdirs-to-load-path emacs.d)
(load "init")
All my other scripts are loaded by ~/Dropbox/source/site-lisp/init.el
and are themselves located in ~/Dropbox/source/site-lisp.
That's how I have the same config on multiple machines.
And here's how .../site-lisp/hooks.el is loaded from init.el:
(load "hooks")
My init.el is about 100 lines, .emacs about 20 lines.
The rest 8000 lines of scripts are sliced into around 20 files.
~/.emacs.d/ does not work like /etc/profile.d/ or /etc/modules-load.d/ or similar directories, i.e. Emacs does not automatically load any Emacs Lisp file in this directory.
In fact, Emacs explicitly advises against placing Emacs Lisp libraries in ~/.emacs.d/. The byte compiler emits a warning if you add ~/.emacs.d/ to the load-path.
Instead, create a new sub-directory, e.g. ~/.emacs.d/lisp. Add this directory to your load-path explicitly, with the following code in init.el:
(add-to-list 'load-path (locate-user-emacs-file "lisp"))
Then, place your Emacs Lisp files in this directory, e.g. ~/.emacs.d/lisp/foo.el, and load them in your init.el:
(load "foo" nil 'no-message)
The best approach to avoid the dreaded .emacs bankruptcy is to actually avoid large customizations! Most notably, try to avoid any custom functions and commands.
Instead, try to a find an ELPA package that comes closest to what you want, and either try to get used to it, or customize it to your needs. If you don't find any, first try to write your own and distribute it on Github, Marmalade or MELPA.
Don't be afraid of maintaining a package in the public. You'll have to maintain your customization anyway, whether in your init.el or not, so you can just as well let other Emacs users help you with this job.
Adding code to your init.el should be your very last resort!

How to make Emacs C source directory permanent?

I'm new to Emacs and I'm just learning how to use it. I know how to set my "Emacs C Source dir" but I don't know how to make this change permanent. I guess I have to set it in my .emacs file but I don't know what is the command for it. Can someone help?
Ordinarily most user-settable variables can be edited with Customize, but for some reason the source-directory variable isn't one of them.
You will need to edit your ~/.emacs file to include a line such as:
(setq source-directory "/path/to/emacs/source/dir")
Do not include the trailing src directory; it will be added automatically. Then exit and restart Emacs.
Note that setting this after Emacs is running may have no effect because it's only read when find-func.el is loaded. You can set find-function-C-source-directory instead (with the /src), but that can get overwritten. It's better just to (setq source-directory ...) at startup, as above.
Assuming you have a decent locate-style shell-command, this saves you having to remember the path exactly. It should thus still work in your ~/.emacs.d/init.el if you upgrade to a newer version, as long as you still have the sources.
(setq source-directory
(file-name-directory
(shell-command-to-string
(concat "locate --limit 1 emacs-" emacs-version "/src"))))

.emacs, automake and cmake

A long time ago,when I wrote my .emacs setup[1], I used a shell script to compile and join the whole thing. The thing is now very old and "crusty", so I am now rewriting it to replace things such as:
(defmacro make-new-comment( mode face strcom color1 color2)
(list 'progn
`(make-face ',face)
`(if (not (assoc ,strcom ,(intern (concat (symbol-name mode) "-comments-alist"))))
(setf ,(intern (concat (symbol-name mode) "-comments-alist"))
(append ,(intern (concat (symbol-name mode) "-comments-alist")) '((,strcom . ,face)))
)
)
`(modify-face ',face ,color1 ,color2 nil t nil nil nil nil)
)
)
and something occured to me. When compiling I access several environmental variables giving information about the system, for example[2], the full name of most programs called by some mode that uses comint[3]. Rather then reading environmental variables, i could use some autoconf like tool to tweak the .emacs files and then compile them.
The problem is that autoconf is just plain ugly. I considered cmake, but the documentation is very poor especially on constructing your own build system. I'm not familar with alternate systems.
Suggestions?
[1]: To make clear, by .emacs setup I mean the 30 or so files and two subdirs of code that I have. Not to mention several packages that ( well at the time of inclusion ) are not part of the standard emacs distribution.
[2] I've replaced eg with "" since apparently many people do not know that eg means for example. Either that or they don't know what an example is.
[3] Such as diff-mode, and ruby-mode.
which diff?
More details would be useful here. Are these environment variables that you set yourself? or things provided by your distro?
Somewhat ironically, it sounds suspiciously like emacs' incredibly powerful built-in scripting is what you're looking for.
I agree with jkerian: why are you assembling your .emacs from parts? Here is what I do: break it down by language or feature and use require and provide. My .emacs looks like:
; -*- emacs-lisp -*-
(add-to-list 'load-path "~/elisp/personal")
(require 'jdk-generic)
(require 'jdk-haskell)
(require 'jdk-keywiz)
(require 'jdk-lua)
(require 'jdk-ocaml)
(require 'jdk-org)
(require 'jdk-php)
(require 'jdk-tex)
(require 'jdk-text)
(require 'jdk-whitespace)
Each individual file in ~/elisp/personal then sets up support for a language or whatever, then provides jdk-whatever. Here is jdk-lua.el:
(add-to-list 'load-path "~/elisp/packages/lua-mode-20071122")
(add-to-list 'auto-mode-alist '("\\.lua$" . lua-mode))
(autoload 'lua-mode "lua-mode" "Lua editing mode." t)
(provide 'jdk-lua)
Notice that I keep all elisp packages in ~/elisp/packages. This means I can copy my .emacs and ~/elisp directory just about anywhere and have it work straight away.
From what I understand, you want a script to autodetect where are your tools (like diff, grep...) instead of manually telling your .emacs where they are through environment variables.
If you are on a unix-like platform, all your tools like diff, grep, should already be on your PATH and emacs should have no problem finding them. So, in your .emacs you should not use any environment variable and put directly tools name in your configuration.
If your goal is to make a portable .emacs that could be executed on Windows for example, then you should put all the gnuwin32 tools in your PATH too, so that emacs find them without problem. But for Windows, you'll have to do many other tiny arrangements for emacs commands to work properly as on a unix system.
Using a tool like autoconf is something very time-consuming for something that could be well handled by customizing one single .emacs file. If you have specific things to do for a particular system, you could write elisp code like this :
(if (eq window-system 'w32)
(progn ... ))
Also, if you want to automate the byte compilation of all your .el files, you could use a command like this on your shell :
emacs --batch -f batch-byte-compile *.el

Let emacs choose mode conditionally when opening files

I use the php debugger geben and nxhtml-mode -- my standard mode for editing php files. Unfortunately, these two modes don't mix well. Is it possible to configure emacs such a way that it enables nxhtml only conditionaly, when I open php files manually, but enables php-mode instead when the buffer is opened by geben?
Okay, I seem to have fixed it. Warning! I really don't know what I'm doing -- these are my first steps in lisp and I found it by trial and error. I've added this to the end of my .emacs file:
(require 'geben)
(defun geben-enter-php-mode ()
(let* ((local-path (buffer-file-name))
(session (and local-path (geben-source-find-session local-path))))
(if session
(let ((session nil))
(php-mode)))))
(add-hook 'find-file-hook #'geben-enter-php-mode)

Is there a good way to do Emacs project?

I use emacs to do some coding, and text editing. When I create a new coding project, I simply create a new folder, and add source code into it.
The problem is, with multi-folders, it is hard to change back to the
top, and run the makefile.
Is there any good method to do project management like eclipse or
other IDEs?
I know your problem. If you have a Makefile in the same folder as your source, and you are in a source buffer, then 'compile' will build correctly.
But if your source is in a different folder then emacs can't find the Makefile.
One solution is to specify the Makefile's location by setting the 'default-directory' variable as a file variable in each source file.
You do this by adding a line like this at the top of the file (and reload it).
// -*- mode: C++; default-directory: "c:/somewhere/yourmakefiledirectory/" -*-
Below is the ;; compilation section of my .emacs file. I use CTRL+F7 for make, and F7 for make clean. It will search in the current directory and then in .. and so on for a file called "Makefile" to run make on.
Also not that F8 jumps the source window to the first error and CTRL+F8 takes you to the previous error. (BTW, if you think this is awesome, you should see what I've done for GDB integration)... :)
;; Compilation
(setq compilation-scroll-output 1) ;; automatically scroll the compilation windo
w
(setq compilation-window-height 10) ;; Set the compilation window height...
(setq compilation-finish-function ;; Auto-dismiss compilation buffer...
(lambda (buf str)
(if (string-match "exited abnormally" str)
(message "compilation errors, press F6 to visit")
; no errors, make the compilation window go away after 2.5 sec
(run-at-time 2.5 nil 'delete-windows-on buf)
(message "No compilation errors!"))))
(require 'cl) ; If you don't have it already
(defun* get-closest-pathname (&optional (file "Makefile"))
"This function walks up the current path until it finds Makefile and then retu
rns the path to it."
(let ((root (expand-file-name "/")))
(expand-file-name file
(loop
for d = default-directory then (expand-file-name ".." d)
if (file-exists-p (expand-file-name file d))
return d
if (equal d root)
return nil))))
(defun my-compile-func ()
"This function does a compile."
(interactive)
(compile (format "make -C %s" (file-name-directory (get-closest-pathname)))))
(defun my-compile-clean-func ()
"This function does a clean compile."
(interactive)
(compile (format "make -C %s clean" (file-name-directory (get-closest-pathname
)))))
(defun my-compile-package-func ()
"This function builds an Endura package."
(interactive)
(compile (format "make -C %s package" (file-name-directory (get-closest-pathna
me)))))
(global-set-key [f7] 'my-compile-clean-func)
(global-set-key [C-f7] 'my-compile-func)
(global-set-key [S-f7] 'my-compile-package-func)
(global-set-key [f8] 'next-error)
(global-set-key [C-f8] 'previous-error)
Just M-x compile once from the root directory. This will create a *compilation* buffer which will remember the directory and parameters it was invoked with.
Then when you want to recompile, just issue M-x recompile. This works from anywhere. It brings back up your original *compilation* buffer and uses the directory stored in that buffer to find your Makefile.
There are other ways to issue compilation from outside your project's root directory, but I thought I'd point this out since it works out of the box with zero customization. A lot of the other responses made the solution sound more complicated than it is.
Compilation buffer tips
If you type C-c C-f while in the compilation buffer it will enable next-error-follow-minor-mode, so that while you navigate among the errors of the compilation buffer, a second window will display the error in it's original source buffer.
M-n and M-p will move between the errors of the compilation buffer.
If you are already in the source buffer, and want to navigate between errors there, type M-g n, or M-g p.
Syntax Error Highlighting
Type M-x flymake-mode to do on the fly syntax checking as you type. It will highlight syntax errors in red. Hovering over with the mouse will show you the error message.
For flymake to work, you must add a check-syntax rule to your makefile.
C++ example:
check-syntax:
g++ -o nul -S ${CXXFLAGS} ${CHK_SOURCES}
This rule checks the syntax of the file, but does not compile it, so it is fast.
I don't generally compile from within emacs anymore, but why can't you run a shell in a buffer just for running make. Keep that shell in the top level directory.
As for project management, what features are you looking for?
I use EDE from CEDET package - it can maintain different types of projects. I use it to work with CMake, together with custom compile-command (you can find it here - see for MyCompile function)
I recently started using project-root to manage my various directory trees. I've now bound F5 to (with-project-root (compile)) and the default-directory is automatically set to the root of any project that I've specified in my .emacs, based on whatever buffer I'm invoking the compile from.
I'm not sure exactly what you're asking, but you might be looking for Speedbar.
You can use Desktop bookmarks, Dired bookmarks, or Bookmark-List bookmarks to organize a project -- see Bookmark+.
See also: Icicles support for projects for more options.
bookmarksbookmark
Depends on the language. JDE is a good Java environment, Distel is a good Erlang environment. I'm sure there are good environments for other platforms as well. Across the board, though, you'll have to do more configuration in emacs than you will in an IDE like Eclipse. IMO, the payoff is worth it, though.
How about entering the following when prompted for the compiling command:
"cd <root> ; make"
If it's a hassle to type often, it can be set in the "compile-command" variable -- though it will be remembered in a session after you type it once.
when I did this with Java, I used ANT, and ANT handled this elegantly with the "-find" switch.
Effectively what it did was look in the current directory for the build.xml file, until it found it. Very handy especially in Java projects because of their enforced directory structure.
For Make, I would create a similar replacement:
#!/bin/sh
# mymake -- my "hunt the makefile" make command
if [ -f Makefile ]
then
exec make
else
cur=`pwd`
if [ $cur = "/" ]
then
echo "Can not find Makefile"
exit 1
fi
newdir=`dirname $cur`
cd $newdir
exec mymake
fi
I would use eproject; http://github.com/jrockway/eproject
Here's an example from SO: Is there a good Emacs project management somewhere?
Basically, it unifies the features of CEDET, project-root, and so on. You can declare project definitions in a number of ways, and access the data through a unified API. It also comes with some nice sugar, including ibuffer integration. (Filter ibuffer by project, see the project name next to the buffer name, etc.]