Every time I start work, I fire up Emacs, M-x cd to a working directory, M-x slime to start Slime, then do run (ql:quickload 'myproject) in the slime repl, (or , load-system myproject) followed by , +p myproject to switch the current package in the repl.
Lastly I run call a (start-server) in the repl to get my web server started.
I'd like for this all to be just a single Emacs keystroke or command. It's embarrassing that I have to ask this, since it's all lisp, but I can't quite figure out the interplay between Emacs and Slime here. Yet as a programmer I feel like I should automate all tedious processes - and I foresee several more steps being added to this.
I guess the tricky part is sending slime commands and then waiting for quicklisp to finish before sending the next command.
Any pointers would be appreciated!
Edit: Thanks to Svante for the C-c ~ hint, which was news to me
On the Emacs side, you can bind a key to a command than calls slime with additional arguments:
(defun my-lisp ()
(interactive)
(slime (concat "sbcl --load " <path-to-your-lisp-script>)))
And in your Lisp script, for example:
(ql:quickload :my-system)
(in-package :my-package)
(start-server)
It's probably very easy but I simply can't get a running scheme REPL in emacs.
First I installed MIT scheme and added
(setq scheme-program-name "my/path/to/bin/mit-scheme.exe")
to my init.el. But when I typed M-x run-scheme RET I got the error
Required feature ‘scheme’ was not provided
So I installed quack and added (require 'quack) to my init.el
Now when I start emacs I get the same error:Required feature ‘scheme’ was not provided
Am I missing a step?
Update
Maybe it simply doesn't work under windows:
Running Scheme under gnu-emacs If you want to run Scheme as an
inferior process in gnu-emacs or xemacs (again, this is not an option
on Windows machines), then you'll need to:
Download the xscheme.elc file. This is a byte-compiled elisp file that tells emacs how to run and interact with MIT Scheme. (Source file
is xscheme.el in case you're interested.)
This file should replace the xscheme.elc file that comes with emacs. You'll have to find the appropriate directory on your system.
On my Mandrake Linux system, this is the directory:
/usr/share/emacs/21.3/lisp. (This step is not necessary if you are
running MIT/GNU Scheme from the CS department machines.)
Add the following line to your ~/.emacs file
(load-library "xscheme")
Source (from 2005): http://www.cs.rpi.edu/academics/courses/fall05/ai/scheme/starting.html
Following doesn't work either
Quick Setup
Here is the short list of instruction's for those of you who want to
get started in a hurry. An explanation of each step follows below.
Open up emacs (or any other editor) in you home directory.
Open up the file ".emacs" and add the following line: (set-variable (quote scheme-program-name) "stk")
Save the file. You only need to do steps 1-3 once. If you were editing the file in Emacs, restart Emacs.
Start up Emacs and type the following sequence of keys:
M-x
run-scheme
A new buffer will open up with stk started inside of it.
Source: http://www-users.cs.umn.edu/~gini/1901-07s/emacs_scheme/
The error "required feature scheme was not provided" means that the first "scheme.el" found in your load-path does not contain a provide statement. Either your Emacs installation is broken (unlikely), or (more likely) you've installed some random scheme.el that hides the default one. Find it and remove it. Eg try M-x list-load-path-shadows.
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.
I'm trying to get JSHint to work with Flymake.
jshint is indeed installed in /opt/bin and works. /opt/bin is in Emacs' exec-path.
I've followed the directions on the EmacsWiki and have this in my init.el:
(defun flymake-jshint-init ()
(let* ((temp-file (flymake-init-create-temp-buffer-copy
'flymake-create-temp-inplace))
(local-file (file-relative-name
temp-file
(file-name-directory buffer-file-name))))
(list "jshint" (list local-file))))
(setq flymake-err-line-patterns
(cons '("^ [[:digit:]]+ \\([[:digit:]]+\\),\\([[:digit:]]+\\): \\(.+\\)$"
nil 1 2 3)
flymake-err-line-patterns))
(add-to-list 'flymake-allowed-file-name-masks
'("\\.js\\'" flymake-jshint-init))
When I open JavaScript files, my modeline appears as:
[(Javascript Flymake* AC)]
This is odd because the * usually doesn't appear when I'm using Flymake with C++ or Python. According to the Flymake docs, Flymake* means "Flymake is currently running." However, Flymake isn't showing any errors.
I've checked the *Messages* buffer but it only lists a few lines of Fontifying foo.js... (regexps...................). No errors.
Other suggestions?
Try using M-: to execute (setq flymake-log-level 3), which will cause flymake to print debug info into *Messages*.
Here's how I use flymake with jslint, which works nicely for me -- that code might give you a clue about what's going wrong for you.
You might also consider js2-mode, which provides some language-aware lint-like warnings without resorting to running an external process.
I found a project called jshint-mode and tried that. It created a buffer called *jshint-mode* which revealed the error: JSHint couldn't find the formidable module.
I ran M-x setenv in Emacs to set NODE_PATH so that jshint could find the formidable library. I also set NODE_PATH in /etc/profile.
jshint-mode did not work for me (I use Linux Mint 14 'Nadia') -- I was getting errors with "flymake's configuration" when it runs curl to talk to the Node.js instance running the jshint script. This was perplexing, and I'm not familiar with ELisp to go around messing with the .el files.
I solved this by instead going straight to the Emacs flymake project fork on github which now has support for jshint built-in (it needs to be installed as npm -g install jshint which in turn requires you to install npm and node.js if you haven't already). This made things work.
One more caveat: on my Linux box, node was an executable already existing in /usr/sbin and I had to make a symbolic link named node in /usr/local/bin to override the former. This was necessary as the Node.js binary for Linux Mint (possibly Ubuntu as well, I haven't checked) is named nodejs instead and will cause many scripts written assuming a binary name of node to fail. You can test this by typing node: if it is the pre-existing binary it generally returns to the prompt silently, but if it is Node.js it prompts you with a > (you can Ctrl-D to quit out of there)
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.]