Setting byte-compile-dest-file-function - emacs

I want to set the destination directory for emacs lisp byte compilation using relative path such as ../foo. I figured out I should use byte-compile-dest-file-function, but do not know how to set it. How can I set it?

To set the byte-compile-dest-function variable, you can use either customize-variable interactively, or setq in your init file. Since you'll have to write a function doing the job either way, I would recommand the latter, so that everything is in the same place in your init file.
For example:
(defun my-dest-function (filename)
(concat (file-name-directory filename)
"../"
(file-name-sans-extension (file-name-nondirectory filename))
".elc"))
(setq byte-compile-dest-file-function 'my-dest-function)

You can find it using C-h v followed by that variable name.
(defcustom byte-compile-dest-file-function nil
"Function for the function `byte-compile-dest-file' to call.
It should take one argument, the name of an Emacs Lisp source
file name, and return the name of the compiled file."
:group 'bytecomp
:type '(choice (const nil) function)
:version "23.2")
You can see that it is a customizable variable, so you can change it's value to "function".
EDIT: I am not so sure this is the variable you want to change. In fact, you can see that it deals with the variable directories often, I don't see how to set a certain directory where all the .elc's should go.

Related

How to configure Emacs to save backup for files under temp directory?

I use emacsclient to edit temp files in /tmp a lot and would like to create backup copies of my files automatically like we do with other files. I'm sure there is a way to do it - but how? :)
(I searched the Emacs manual, emacswiki and SO but couldn't find anything useful)
Look at the normal-backup-enable-predicate function, which is the default value for the backup-enable-predicate variable.
As the sole purpose of the default function is to inhibit backups for files in various temporary directories, you may just want to set a replacement which returns t unconditionally.
(setq backup-enable-predicate (lambda (name) t))
The usage in files.el suggests to me that you could also just set this variable to nil. That's not stated in the documentation, so it might not be reliable, but the variable isn't referenced by any other library in Emacs, so it's probably fine (but I'd still recommend using the lambda, because it's more obvious what that's doing).
See also C-hig (elisp) Making Backups RET
n.b. I'm not actually familiar with small-temporary-file-directory (see the docstring for that variable), but the temporary-file-directory value would typically be /tmp/, so those two cases are usually the same.
If you did want to retain the default behaviour for some temporary directories but not others, you should define a modified copy of the original function: (defun my-backup-enable-predicate ...) and then (setq backup-enable-predicate 'my-backup-enable-predicate)
Stick this in yer .emacs file:
;; create an invisible backup directory so our directories
;; look a bit cleaner
;; thanks to #emacs in irc.freenode.org, Ryan Barrett of snarfed.org
;; and freethegnu.wordpress.com
(defun make-backup-file-name (filename)
(defvar backups-dir "/tmp/")
(make-directory backups-dir t)
(expand-file-name
(concat backups-dir (file-name-nondirectory filename) "~")
(file-name-directory filename)))

How do I get the path from which init.el was loaded?

I am looking to create a custom config for emacs to use for Erlang work and I want to refer to my custom EDTS repo as being under the directory from which init.el was loaded. Right now I have this:
(add-to-list 'load-path "~/.emacs-edts/edts/")
But I would rather not hardcode it and refer to it by variable.
Suggestions?
Strictly speaking the answer is (file-name-directory user-init-file), but instead see C-hv user-emacs-directory
I have the following snippet in my init.el:
(setq my-init-dir
(file-name-directory
(or load-file-name (buffer-file-name))))
This has the advantage of working whether init.el is in your emacs.d directory or not.
I have the following in my init file:
(defun my-file-name-basename (s)
"The directory name, without the final part.
For example:
(my-file-name-basename \"alpha/beta/gamma\") => \"alpha/beta\""
(substring (file-name-directory s) 0 -1))
;; Note: Normally, it's not possible to find out the file a specific
;; function is defined in. However, it's possible to save the file
;; name at the time this file was loaded.
(defvar my-load-file-name load-file-name
"The file name of this file.")
(defun my-start-directory (&optional path)
"The root directory that contains this module.
When PATH is specified, return the start directory concatenated with PATH.
Otherwise return the directory with a trailing slash."
;; Note: Try to figure out where we are, so that we can add the
;; subdirectories. `load-file-name' only works when the file is
;; loaded. Picking up the file from the symbol works when this is
;; evaluated later.
(let ((file-name (or my-load-file-name
(symbol-file 'my-start-directory)
;; Default value. (This is used, for example,
;; when using `eval-buffer' or `eval-region'.)
"~/emacs")))
(let ((start (concat (my-file-name-basename
(my-file-name-basename file-name))
"/")))
(if path
(concat start path)
start))))
In addition to finding out where the file containing the above above code is located (which does not have to be the init file), it provides a convenient way to create paths based on it. For example:
(setq custom-file (my-start-directory "init/custom.el"))

emacs: load-path and require (cannot open load file)

I've got "Cannot open load file" error at (require 'org-mime) while load-path variable seems to be all right:
load-path is a variable defined in `C source code'.
Its value is
("/home/alexey/.emacs.d/elpa/bbdb-20130526.1945" "/home/alexey/.emacs.d/elpa/org-mime-20120112" "/home/alexey/.emacs.d/elpa/smex-20130421.2153" "/usr/share/emacs/24.3/site-lisp" "/usr/share/emacs/site-lisp" "/usr/share/emacs/24.3/lisp
...
Curiously, the remedy looks like this (.emacs):
(add-to-list 'load-path "~/.emacs.d/elpa/org-mime-20120112")
It isn't merely ugly: it's dysfunctional, because the versioned path is subject to change. But why the error?
There is an interesting issue that happens when you load a file that requires another file -- the file that is required must be loaded in chronological order before the next file. For example, if B requires A then A must be placed higher up in chronological order so that when B loads, A is already loaded.
I've had really good luck with this type of setup. Most files end with el or elc, so I'm not sure why you want to load a file with a different or no extension, but it is certainly possible to do that if you want.
(let* ((root.d "~/") (sub-dir (concat root.d ".emacs.d/")))
(load-file (concat sub-dir "init.el"))
(setq load-path
(append `(,root.d ,sub-dir
,(concat sub-dir "elpa/yasnippet")
) load-path)))

How to make emacs auto-name buffer based on filename?

I often load many 00readme.txt files into emacs, and the default
buffer name "00readme.txt" isn't very helpful.
I use rename-buffer manually to rename them "project1", "project2", etc.
How do I tell emacs: "when loading /foo/bar/00readme.txt,
automatically name the buffer project1, not 00readme.txt"?
You might also want to look at the uniquify library shipped with emacs, which can add parts of the directory name to the buffer name, when opening files with the same name.
;; toss this into your .emacs file and fiddle with it till you get what you want
(defun my-buffer-renamer()
(interactive)
(let () ; <-- local vars in here
(message "bufer name is %s" (current-buffer))
(rename-buffer "something else") ; make sure to make unique names
))
(add-hook 'text-mode-hook 'my-buffer-renamer) ; only do this once
Emacs supports a plethora of 'hook' functions, callbacks that get executed when a particular action occurs. Here, we add a function to gets invoked when a text file get's loaded.
Here's a nice configuration for uniquify, which is the standard Emacs way to solve your problem:
(require 'uniquify)
(setq uniquify-buffer-name-style 'reverse)
uniquify-separator " • "
uniquify-after-kill-buffer-p t
uniquify-ignore-buffers-re "^\\*"

Emacs: Set tab indent for just one file on the fly

I work on an open source project where the creator sets his tab-indents to 2 spaces.
I'd like to just enable it on the fly for the one file I work on and not other files of the same type. There must be something like M-x set-tab-indent. It is a JavaScript file ending in .js.
I know I can use:
(setq-default tab-width int)
inside my .emacs file, but I rather just call an M-x command to set it and forget it during my duration of working on this file. I tried M-x apropos and Google but couldn't find the specific command.
Thanks.
You can make the variable js-indent-level local to the buffer using:
M-x make-variable-buffer-local <RET> js-indent-level <RET>
Then you can set that variable in the buffer using:
M-x set-variable <RET> js-indent-level <RET> 2
The easiest way to do this for a single buffer is to use M-x set-variable.
Type M-x set-variable and press enter
When prompted for the variable to set, set tab-width then press enter
You'll be prompted with the line Set tab-width (buffer-local) to value:.
Put the value you want, then hit enter
The buffer should instantly be updated with the new value.
You could also use file local variables to automate omrib's solution for that one file, by adding this to it:
// Local Variables:
// js-indent-level: 2
// indent-tabs-mode: nil
// End:
Create a file ".dir-locals.el" in the project's directory and fill it like this:
((nil . ((tab-width . 2))))
This will take care of setting tab-width automatically and you don't have to modify the actual file (which is likely version-controlled.)
See the manual for more information about the format. I believe this requires Emacs 23.
As indicated by others, one issue with the File Local Variables approach is that you need to modify the file, and that's not ideal if you need to keep those declarations out of version control.
If you want the variables to apply to all files under a given directory, then Directory Local Variables is obviously the way to go, and you can implement that with either a .dir-locals.el file, or by calling (dir-locals-set-directory-class):
http://www.emacswiki.org/emacs/DirectoryVariables
http://www.gnu.org/software/emacs/manual/html_node/emacs/Directory-Variables.html
I prefer the directory class approach myself, and I was thinking that it's a shame that there isn't an analogous approach for file local variables, but I found that the directory class code actually works perfectly with files, and the only issue is that dir-locals-set-directory-class calls file-name-as-directory on its argument, which prevents it from being matched, due to the trailing slash.
The following therefore is a way to configure directory local variables for a single file, without modifying the file itself, or affecting other files under the same parent directory.
(defun my-file-locals-set-directory-class (file class &optional mtime)
"Enable 'directory local' classes for individual files,
by allowing non-directories in `dir-locals-directory-cache'.
Adapted from `dir-locals-set-directory-class'."
(setq file (expand-file-name file))
(unless (assq class dir-locals-class-alist)
(error "No such class `%s'" (symbol-name class)))
(push (list file class mtime) dir-locals-directory-cache))
(dir-locals-set-class-variables
'my-javascript-class
'((nil . ((js-indent-level . 2)
(indent-tabs-mode . nil)))))
(my-file-locals-set-directory-class
"path/to/the/file.js" 'my-javascript-class)
I use a snippet of code in my init.el that tries to auto-detect files that use 2-space indents, and switch Emacs's indentation for that file to 2 spaces when it sees such files:
(add-hook 'js-mode-hook
(lambda ()
(when (string-match-p "^ [A-Za-z]" (buffer-string))
(make-variable-buffer-local 'js-indent-level)
(set-variable 'js-indent-level 2))))