How to force byte compile a directory in elisp - emacs

How to byte compile a directory forcibly without caring about anything in elisp source (means the same as the interactive one: C-u 0 M-x byte-recompile-directory but in source)?
Need I write something like:
(defun byte-compile-directory-recursively (directory)
(dolist (file (directory-files directory t "\\w+"))
(if (file-directory-p file)
(byte-compile-directory-recursively file)
(if (string-match "\\.el$" file)
(byte-compile-file file)))))
? Any help is appreciated.

I believe you are looking for (byte-recompile-directory directory 0).

Related

Emacs: extending dired-do-compress to directories

If I press 'Z' in dired (or x-dired) mode in emacs, the file under the cursor is compressed or uncompressed.
I'd like to extend this behavior to directories. That is, if the cursor is at a directory "stuff", I'd like 'Z' to run
tar -zcf stuff.tgz stuff
(on the assumption that 'tar' is provided by the OS).
Side note:
The converse (expanding stuff.tgz into the full directory tree) can already be done by '!', which suggests guesses for expansion. The asymmetry ('Z' to compress and '!' to uncompress) does not bother me.
Cool idea. Here's a start that works for me: just need to change a few lines in dired-compress-file. I've highlighted the changes with BEGIN EDIT and END EDIT comments (sorry if there's a better way to highlight a diff). I'm sure this isn't robust, but maybe it can point you in the right direction.
EDIT: I should say that the below works for me in GNU Emacs 24.3.1.
(defun dired-compress-file (file)
;; Compress or uncompress FILE.
;; Return the name of the compressed or uncompressed file.
;; Return nil if no change in files.
(let ((handler (find-file-name-handler file 'dired-compress-file))
suffix newname
(suffixes dired-compress-file-suffixes))
;; See if any suffix rule matches this file name.
(while suffixes
(let (case-fold-search)
(if (string-match (car (car suffixes)) file)
(setq suffix (car suffixes) suffixes nil))
(setq suffixes (cdr suffixes))))
;; If so, compute desired new name.
(if suffix
(setq newname (concat (substring file 0 (match-beginning 0))
(nth 1 suffix))))
(cond (handler
(funcall handler 'dired-compress-file file))
((file-symlink-p file)
nil)
((and suffix (nth 2 suffix))
;; We found an uncompression rule.
(if (not (dired-check-process (concat "Uncompressing " file)
(nth 2 suffix) file))
newname))
(t
;;; We don't recognize the file as compressed, so compress it.
;;; Try gzip; if we don't have that, use compress.
(condition-case nil
;; BEGIN EDIT - choose the correct name if looking at a directory
(let ((out-name (if (file-directory-p file) (concat file ".tar.gz") (concat file ".gz"))))
;; END EDIT
(and (or (not (file-exists-p out-name))
(y-or-n-p
(format "File %s already exists. Really compress? "
out-name)))
;; BEGIN EDIT: create a tarball if we're looking at a directory
(not (if (file-directory-p file)
(dired-check-process (concat "Compressing " file)
"tar" "-zcf" out-name file)
(dired-check-process (concat "Compressing " file)
"gzip" "-f" file)))
;; END EDIT
(or (file-exists-p out-name)
(setq out-name (concat file ".z")))
;; Rename the compressed file to NEWNAME
;; if it hasn't got that name already.
(if (and newname (not (equal newname out-name)))
(progn
(rename-file out-name newname t)
newname)
out-name)))
(file-error
(if (not (dired-check-process (concat "Compressing " file)
"compress" "-f" file))
;; Don't use NEWNAME with `compress'.
(concat file ".Z"))))))))
The following is a link to the library dired-tar -- it tars and compresses directories and files. I have verified it works on OSX with a recent version of Emacs Trunk built on March 19, 2014.
http://www.emacswiki.org/emacs/DiredTar
This functionality is now installed in master:
press Z on a directory to run tar -czf dirname.tar.gz dirname
press Z on a *.tar.gz file to run tar -zxvf dirname
The latter can be customized via dired-compress-file-suffixes, if you ever need to use something other than -zxvf.

Erlang flymake with nested folders in src cannot find includes folder

Sorry for my poor English.
I'm configuring my emacs with erlang flymake. Source files in src's nested folders report 'can't find include file', but files in src/folder can find the include file.
My emacs settings for erlang:
;; erlang-mode
(setq load-path (cons "/usr/local/Cellar/erlang/R15B02/lib/erlang/lib/tools-2.6.8/emacs" load-path))
(setq erlang-root-dir "/usr/local/Cellar/erlang/R15B02/lib/erlang")
(setq exec-path (cons "/usr/local/Cellar/erlang/R15B02/lib/erlang/bin" exec-path))
(require 'erlang-start)
;; distel
(add-to-list 'load-path "/usr/local/share/distel/elisp/")
(require 'distel)
(distel-setup)
;; erlang-flymake
(require 'erlang-flymake)
(erlang-flymake-only-on-save)
My erlang application folder is like following:
app/src/ (source code)
src/mod
src/lib
app/include/ (hrls)
app/ebin/ (compiled code)
...etc
In erlang-flymake there are 2 variables (erlang-flymake-get-include-dirs-function and erlang-flymake-get-code-path-dirs-function), that specify functions to search include & ebin directories. Right now, they're pointing to the functions erlang-flymake-get-include-dirs and erlang-flymake-get-code-path-dirs that simply return current dir + include and ebin correspondingly. For example, you can use following code to do this:
(defun get-erlang-app-dir ()
(let* ((src-path (file-name-directory (buffer-file-name)))
(pos (string-match "/src/" src-path)))
(if pos
(substring src-path 0 (+ 1 pos))
src-path)))
(setq erlang-flymake-get-code-path-dirs-function
(lambda ()
(concat (get-erlang-app-dir) "ebin")))
(setq erlang-flymake-get-code-include-dirs-function
(lambda ()
(concat (get-erlang-app-dir) "include")))
P.S. Are you using rebar to maintain your project?
If you use erlang-flymake you might want to look at https://github.com/ten0s/syntaxerl. It's a syntax checker for Erlang. It uses erlang-flymake under the hood, but instead of `erlc' it uses a custom syntax checker that can evaluate .erl, .hrl, .config, .rel, .app, .app.src, .escript files. The syntax checker is rebar aware, but also works with standard Erlang/OTP directory structure. Emacs's setup is also there.

change .emacs file's location

I am working on windows xp
I stored emacs in usb
I want to carry the .emacs file as well as binary files
what I tried are
(setenv “HOME” (format "%s" (getenv "emacspath")))
(setenv “HOME” (format "%s/" (getenv "emacspath")))
It seems works if I eval-expression in emacs
After setenv, I could notice setting env is works well by (getenv "home")
but I put the (setenv "home" (format "%s/" (getenv "emacspath")))
in "site-start.el" file in "site-lisp" folder, starting emacs says "Symbol's value as variable is void: "HOME"
Any ideas?
An easier way - just create a batch file on your USB drive where you can set all env variables you need. Then start emacs.exe from the batch.
For example if you want to run SBCL add the following lines to your batch
rem SBCL_HOME is required for SBCL
set SBCL_HOME=%utils%\Lisp\sbcl\1.0.29
set SBCL_RUN=%SBCL_HOME%\sbcl.exe
set SBCL_OPTIONS=--noinform
How about using default.el either as a symlink or as a simple elisp pinter to your file:
(load-file "/path/to/usb/.emacs")
Add following code to a file (e.g. c:/.emacs).
;; This function must be at begin
(defun zxy-relocate-dotemacs ()
"Relocate .emacs file"
(interactive)
(with-temp-buffer
(let (print-level print-length)
(insert (format "(load-file \"%s\")" load-file-name))
(if (file-exists-p "~/.emacs")
(message "[zxy] Don't need relocate .emacs file!")
(progn
(message "[zxy] Relocate .emacs file.")
(write-file "~/.emacs"))))))
(zxy-relocate-dotemacs)
;; Your configuration here
Open emacs and M-x load-file c:/.emacs.
Then it will relocate .emacs to c:/.emacs.
I use this when I copy my emacs to a new computer.
More information please visit my blog abuot emacs.
http://coordinate.sinaapp.com/?cat=3

How can I access the path to the current directory in an emacs directory variable file?

According to the Emacs documentation, Directory Variables apply to all files below a directory that contains an .dir-locals.el file.
How can I, in that file, set a variable to the full path that contains the file? For example:
((nil . ((indent-tabs-mode . t)
(my-project-path **THIS_DIRECTORY**))))
I asked myself the same question and found no solution on the web, so I think this answer may help. Actually, it turns out we can reuse dir-locals-find-file to get the directory containing the .dir-locals.el file. So here's what I found for, e.g, setting up an aspell personal dictionary dedicated to a whole directory:
((nil . ((eval . (setq ispell-personal-dictionary
(expand-file-name
".aspell_words"
(file-name-directory
(let ((d (dir-locals-find-file ".")))
(if (stringp d) d (car d))))))))))
Also, it seems entries are evaluated in the order they are specified, so the following code should work:
((nil . ((eval . (set (make-local-variable 'my-project-path)
(file-name-directory
(let ((d (dir-locals-find-file ".")))
(if (stringp d) d (car d))))))
(eval . (message "Project directory set to `%s'." my-project-path)))))
Emacs will complain about unsafe local variables (due to the eval construct), yet one can still permanently mark it safe.
Update: Since Emacs ≥ 26.3 (and maybe older versions as well), it appears that one needs to use (dir-locals-find-file "./") instead of (dir-locals-find-file ".").
I think (file-name-directory (or load-file-name buffer-file-name)) should give you the directory path.
See Link
Edit: Except it won't, because any eval expressions are evaluated in the context of the buffer whose variables are being hacked.
In my case, I wanted to locate a file that was relative to my current working directory for my repository, and the .dir-locals.el file was checked into the root, so a file "local" to the .dir-locals.el was also a file "local" to the project root.
pajato0's answer above worked for some cases, but it was also breaking other modes (like magit). I got around the issue by using the projectile package's projectile-project-root function to find my the base path for me:
((nil . ((eval . (setq cmake-ide-build-dir
(concat (projectile-project-root) "/build-make"))
))))
I've found the locate-dominating-file procedure, which comes out-of-the-box with Emacs, useful to retreive the current directory of a known file. The example below sets the guix-directory variable to the topmost directory of the project containing a .dir-locals.el file.
((nil . ((eval . (setq guix-directory
(locate-dominating-file default-directory
".dir-locals.el"))))))
It's not a safe .dir-locals.el setting, due to relying on eval, but it gets the job done.
In case it still matters, to the OP or some other, I would suggest you create a function to generate the .dir-locals.el file. Then one could write something like:
(let ((path default-directory)
file)
(setq file (format "%s/.dir-locals.el" path))
(with-temp-buffer
(insert (format "((nil . ((indent-tabs-mode . t)
(my-project-path \"%s\"))))" path))
(when (file-writable-p file)
(write-region (point-min)
(point-max)
file))))
to be executed within the project home directory.
hack-local-variables is the main function for processing all local variables, and it calls hack-dir-local-variables to deal with the .dir-locals.el file (or a dir local class variable, if you're not using that file).
The code for establishing the directory is not isolated in its own function, so we'll have to copy it out into a new function (this from GNU Emacs 24.0.95.1):
(defun my-dir-locals-dir ()
"Return the directory local variables directory.
Code taken from `hack-dir-local-variables'."
(let ((variables-file (dir-locals-find-file (or (buffer-file-name) default-directory)))
(dir-name nil))
(cond
((stringp variables-file)
(setq dir-name (file-name-directory variables-file)))
((consp variables-file)
(setq dir-name (nth 0 variables-file))))
dir-name))
If you are working on *nix, you might get the work directory by the following elisp code,
(defun get-working-directory ()
(getenv "PWD))
Btw, I have to mentioned that, (shell-command "pwd") will result in the directory where file (which is corresponding to the buffer you are currently editing).

Erlang emacs mode - setting outdir

Does anyone know how to configure Erlang emacs mode so that compiling a buffer [C-c C-k] writes the beam file to the ebin directory rather than the current directory ?
Thanks!
You might want to have a look to this thread on the Erlang Questions Mailing List:
http://www.erlang.org/pipermail/erlang-questions/2007-August/028367.html
Moreover, you should be able to compile your file in debug mode:
C-u C-c C-k
The erlang-compile command should support prefix arguments. You might want to have a look to:
http://www.gnu.org/software/emacs/manual/html_node/elisp/Prefix-Command-Arguments.html
If you set up your directory structure like so:
/
/src/
/ebin/
and place your module (e.g. "my_file.erl") in the "/src/" directory then compile it (C-c C-k) then Emacs should automatically put the beam into the "/ebin/" directory.
However, if your module isn't in a directory named "/src/" (or if the "ebin" directory is missing) the beam will be dropped alongside the source file.
To see exactly how this works take a peek at $ERL_TOP/lib/tools/emacs/erlang.el and search for "ebin". Here's what you'll find:
(defun inferior-erlang-compile-outdir ()
"Return the directory to compile the current buffer into."
(let* ((buffer-dir (directory-file-name
(file-name-directory (buffer-file-name))))
(parent-dir (directory-file-name
(file-name-directory buffer-dir)))
(ebin-dir (concat (file-name-as-directory parent-dir) "ebin"))
(buffer-dir-base-name (file-name-nondirectory
(expand-file-name
(concat (file-name-as-directory buffer-dir)
".")))))
(if (and (string= buffer-dir-base-name "src")
(file-directory-p ebin-dir))
(file-name-as-directory ebin-dir)
(file-name-as-directory buffer-dir))))
Not sure when this goody was added, but it was in OTP_R13B03 and it works for me in R14B03.