Is there a good way to do Emacs project? - emacs

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.]

Related

Cross compile on Emacs

How do I create/issue compilation command on Emacs, so I don't need to switch back and forth between it and console? My usual compilation procedure I'd like to see as Emacs command:
$ export PATH=/toolchain/gcc-linaro-arm-linux-gnueabihf-4.7/bin:$PATH
$ cd my/project
$ make CROSS_COMPILE=arm-linux-gnueabihf- all
I tried to make my own version of M-x compile command following instructions, but failed as I'm not familiar with Lisp and Emacs internals enough. Please note, that projects in question are big (i.e. kernel) with multi directories and Makefiles, so the approaches (closest Makefile, default directory etc.) described in the previous link are not a solution. Bonus points if you could bind it to a single key, like Fx key on modern IDEs.
P.S. I'm aware that there's similar question, but it's outdated and doesn't cover cross compile issue, I hope there's a better solution nowadays.
You can create a custom function that runs a specific compile command in a specific directory, like this:
(defun my-compile ()
(interactive)
(let ((default-directory "~/my/project"))
(compile "export PATH=/toolchain/gcc-linaro-arm-linux-gnueabihf-4.7/bin:$PATH && make CROSS_COMPILE=arm-linux-gnueabihf- all")))
And then bind it to some convenient key:
(global-set-key [f12] 'my-compile)
Ctrl U Meta x compile should ask you what compilation command to use. You could type make CROSS_COMPILE=arm-linux-gnueabi all
Otherwise, configure your compilation-command Emacs variable, perhaps in your ~/.emacs; and you might make that a file-local variable.
You could put in your ~/.emacs the following untested lines
(load-library "compile")
(global-set-key [f12] 'recompile)
(setq compilation-command "make CROSS_COMPILE=arm-linux-gnueabihf all")
BTW, your export PATH=... could be added e.g. in your ~/.bashrc, or you could have a shell script running that exact make with the appropriate PATH and have that script be your Emacs compilation-command (perhaps even "temporarily", i.e. just in your emacs session)

emacs compile-command find makefile in superior directory

This seems like such an obvious hack I hate to write it myself, but I've had no luck finding it.
I would like an approach to M-x compile that will search upward in the directory tree from cwd to the first directory with a Makefile, after which it runs the make command. So, it's basically
if ./Makefile exists, run the make command
otherwise, cd .. and try again
Stop at $HOME.
The following code defines compile-parent, which locates the nearest Makefile and creates a make command to use that Makefile. It behaves like compile in that it still prompts, showing you the command that it will use, and giving you a chance to edit it, e.g. by specifying a specific target.
(defun compile-parent (command)
(interactive
(let* ((make-directory (locate-dominating-file (buffer-file-name)
"Makefile"))
(command (concat "make -k -C "
(shell-quote-argument make-directory))))
(list (compilation-read-command command))))
(compile command))
You may also want to look at the Projectile extension, which provides a minor mode to detect projects by the presence of VCS metadata or specific build files, with several commands to work from the project root directory, including a projectile-compile command, that runs M-x compile from the project root.

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 install the slime into emacs under Windows7

How to install the slime into emacs under Win7?
I download a compact package with '.tgz'. But it seems for linux. But there is really not one thing for windows(win 32 OS).
I unfold this package and I find there are lots of documents.
It's actually the same as for other operating systems, as far as I can tell. (At least, it always worked for me under FreeBSD/ArchLinux/Win7.) First, you unpack to a location you like, then add something like this to your .emacs (assuming you unpacked somewhere under your user directory):
(add-to-list 'load-path "~/my/path/to/slime/")
;; (add-to-list 'load-path "~/my/path/to/slime/contrib/") ; for optional features
(slime-setup
;; '(slime-fancy slime-asdf slime-references ; optional features
;; slime-indentation slime-xref-browser)
)
(setq slime-lisp-implementations
'((ccl ("~/path/to/ccl/wx86cl"))
(clisp ("~/path/to/clisp-2.49/clisp" "-modern"))) ; giving a command arg
slime-default-lisp 'ccl)
Restart Emacs or type C-x C-e behind each of these toplevel forms. Then, type M-x slime RET (or C-u M-x slime RET if you want to choose between the implementations in slime-lisp-implementations, otherwise slime-lisp-default will be used) and it should just work (it does for me). The setting of slime-lisp-implementations is optional – you can also give the path to your lisp implementation executable by hand when starting Slime.
Assuming you want to use Slime with CL, since there is no Clojure tag. If you want to use it with Clojure, things are unfortunately a little different and both versions don't play very nicely together. The recommended way for use with Clojure, last time I checked, would be installation using the package system of Emacs 24 or, if you're using an older version, ELPA (which is essentially the same).
This worked for me,
Get a Slime copy from https://github.com/slime/slime, either by git clone or by downloading the zip. Unzip and save it in D:/myuser/slime-2.13, for example
Download and install CLISP
Add this to the .emacs file, usually located in C:/users/myuser/AppData/Roaming:
; This is the path where you've saved Slime in the first step
(add-to-list 'load-path "D:/myuser/slime-2.13/")
(require 'slime-autoloads)
; This is the path where CLISP was installed.
; Use Progra~1 for "Program Files" and Progra~2 for "Program Files (x86)"
(setq inferior-lisp-program "/C/Progra~2/clisp-2.49/clisp.exe")

Finding the buffer file name in Emacs when compiling

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.