emacs23 / elisp: how to properly autoload this library? - emacs

I am upgrading to emacs23. I find that my emacs.el loads much more slowly.
It's my own fault really... I have a lot of stuff in there.
So I am also trying to autoload everything possible that is currently "required" by my emacs.el.
I have a module that exposes 12 entry points - interactive functions I can call.
Is the correct approach to have 12 calls to autoload in order to insure that the module is loaded regardless of which function I call? Are there any problems with this approach? Will it present performance issues?
If not that approach, then what?

What you really want is to get the autoloads generated for you automatically, so that your .emacs file remains pristine. Most packages have the ;;;###autoload lines in them already, and if not, you can easily add them.
To manage this, you can put all the packages in a directory, say ~/emacs/lisp, and in there have a file named update-auto-loads.el which contains:
;; put this path into the load-path automatically
;;;###autoload
(progn
(setq load-path (cons (file-name-directory load-file-name) load-path)))
;;;###autoload
(defun update-autoloads-in-package-area (&optional file)
"Update autoloads for files in the diretory containing this file."
(interactive)
(let ((base (file-truename
(file-name-directory
(symbol-file 'update-autoloads-in-package-area 'defun)))))
(require 'autoload) ;ironic, i know
(let ((generated-autoload-file (concat base "loaddefs.el")))
(when (not (file-exists-p generated-autoload-file))
(with-current-buffer (find-file-noselect generated-autoload-file)
(insert ";;") ;; create the file with non-zero size to appease autoload
(save-buffer)))
(cd base)
(if file
(update-file-autoloads file)
(update-autoloads-from-directories base)))))
;;;###autoload
(defun update-autoloads-for-file-in-package-area (file)
(interactive "f")
(update-autoloads-in-package-area file))
If you add 'update-autoloads-in-package-area to your kill-emacs-hook, then the loaddefs.el will automatically be updated every time you exit Emacs.
And, to tie it all together, add this to your .emacs:
(load-file "~/emacs/lisp/loaddefs.el")
Now, when you download a new package, just save it in the ~/emacs/lisp directory, update the loaddefs via M-x update-autoloads-in-package-area (or exit emacs), and it'll be available the next time you run Emacs. No more changes to your .emacs to load things.
See this question for other alternatives to speeding up Emacs startup: How can I make Emacs start-up faster?

Well, who cares how slowly it starts?
Fire it up via emacs --daemon & and then connect using either one of
emacsclient -c /some/file.ext, or
emacsclient -nw
I created aliases for both these as emx and emt, respectively. Continuing once editing session is so much saner...

Ideally you shouldn't have any load or require in your .emacs file.
You should be using autoload instead...
e.g.
(autoload 'slime-selector "slime" t)
You will need to use eval-after-load to do any library specific config, but the upshot is that you won't need to wait for all this to load up front, or cause errors on versions of Emacs that don't have the same functionality. (e.g. Terminal based, or a different platform etc.)
While this may not affect you right now, chances are, in future you will want to use the same config on all machines / environments where you use Emacs, so it's a very good thing to have your config ready to fly.
Also use (start-server) and open external files into Emacs using emacsclient - So you avoid restarting Emacs.

Related

How do I make an interactive command automatically available?

I feel like this question is super basic, but I haven't been able to figure out how to automatically make a simple interactive command available in an Emacs session...
This is in ~/random/exploration/exploration.el.
;;; Code:
;;;###autoload
(defun exploration ()
"a test package"
(interactive)
(message "hi"))
(provide 'exploration)
;;; exploration.el ends here
This is in init.el:
(add-to-list 'load-path (expand-file-name "~/random/exploration"))
exploration isn't available via M-x though. I have to do M-: (require 'exploration) before it appears.
How would I make this command available automatically, like plugins do? I've been poring over the docs for load-path and autoload but can't figure out how to make this happen.
I want to do this so I can put other functions in exploration.el and have them only available after the user first does M-x exploration. That implies that exploration needs to be autoloaded.
Comments on any redundancies in what I've done here, or tips on how I could have debugged this on my own would also be welcome.
The ;;;###autloload comment is just a comment. When Emacs is built (or a suitably intelligent package manager installs your code as a package) it generates an actual autoload, but outside of that, you need to do it yourself.
(autoload 'exploration "exploration" nil t)
Specify an explicit path in the second parameter and you won't actually need the load-path manipulation to accomplish what you describe.
See also https://www.gnu.org/software/emacs/manual/html_node/eintr/Autoload.html
You have to either load the file instead of adding it to the load-path or you need to put (require 'exploration) to your init.el file after adding the folder to the load-path.
Use autoload function:
(autoload 'exploration "exploration")
If you don't modify load-path, you need an absolute path as the second argument.
Alternatively, install your script as a package, either through MELPA (assuming you can get it there), or locally with package-install-file. This will take care about autoloads for you.

How to get emacs to automatically load and save desktop from initial directory?

I usually have 3-4 different projects that I work on at once. So I am trying to figure out how to get emacs to load the desktop from the folder that I open emacs from and also save to that file when I exit from that emacs instance.
All of the docs I have seen either describe how to get emacs to automatically open and save from a default location (which makes multiple desktops impossible), or to manually load and save the desktop to a specific directory (which I am doing now).
Thanks!
Put this to your .emacs:
(setq your-own-path default-directory)
(if (file-exists-p
(concat your-own-path ".emacs.desktop"))
(desktop-read your-own-path))
(add-hook 'kill-emacs-hook
`(lambda ()
(desktop-save ,your-own-path t)))
Upd.: v. 2, ignore on demand.
(setq your-own-path default-directory)
(if (file-exists-p
(concat your-own-path ".emacs.desktop"))
(if (y-or-n-p "Read .emacs.desktop and add hook?")
(progn
(desktop-read your-own-path)
(add-hook 'kill-emacs-hook
`(lambda ()
(desktop-save ,your-own-path t))))))
I have developed a small set of functions to manage multiple desktops: desktop+
You might want to check it out. My workflow is not exactly the same as yours, though:
I always run emacs from the same directory (I run it from a key binding in my window manager), meaning that I can not rely on the starting directory to know which desktop I want to work with
the first time I work on a new project, I call M-xdesktop-create and provide a name. The desktop is then saved to a central location (under "~/.emacs.d/desktops" by default)
each subsequent time I want to work with a saved desktop, I run M-xdesktop-load, and am provided with a list of saved sessions in which I can quickly retrieve the name of the desired session.
Sessions are always saved when emacs exits or you load another session.
For a really simple answer I put this at the end of my .emacs file. It works fine if you save the desktop in the project folder and start emacs from the project folder.
(desktop-change-dir default-directory)

Load and evaluate file from .emacs

I work on many different machines and VMs, each of which might have their own needs regarding options for .emacs. I have a Git repository / subdirectory .common-system with a second Emacs Lisp file .common-system/emacs containing common definitions used for all my systems.
What changes can I make to .emacs which will load and eval my secondary definition file automagically? Bonus points for keeping the secondary file out of my buffer list after startup.
Have you tried:
(load-file ".common-system/emacs")
It works better (as Stefan suggests) if you specify the full path to the file, something like
(load-file "~/.common-system/emacs")
If you stick with you current repository layout, using load-file (as suggested by others) is the way to go.
However, if you name your top-level directory .emacs.d and place the file init.el in it, Emacs will find it and run it automatically. That way, you don't have to hand-edit a .emacs file on each system you use.
You use a (cond), dispatching on variables such as user-login-name, system-type and system-name
(cond
((equal user-login-name
"myname")
;; Stuff
)
((equal system-type 'gnu/linux)
(require 'some-file)
;; some-file, could be any file in load-path, named some-file.el, and ending
;; with (provide 'some-file)
))

Breaking out of .emacs script

I use two emacs (Aquamcs and text based emacs) on my Mac.
I normally use text based emacs for just editing something, so I don't want to load anything with it.
What I came up with is to have the checking code in .emacs to exit/break if it's text based emacs (darwin system but not aquamacs).
(when (and (equal system-type 'darwin) (not (boundp 'aquamacs-version)))
(exit) ??? (break) ????
)
It seems to work, but I don't know how to break out of .emacs. How to do that?
ADDED
I just wanted to speed up in loading text based emacs on my mac, and I thought about breaking out as a solution. Based on the helpful answers, I came up with the following code that runs .emacs only when it's not a text based emacs.
(setq inhibit-splash-screen t)
(unless (null window-system)
I don't know of any way to do exactly what you want. Some workarounds:
You can stop the evaluation of your .emacs by evaluating (error "message") but that's a bit unpleasant.
You can re-order your .emacs so that there's a (unless (CONDITION) ...) around the whole of the file.
You can run emacs -Q FILE when you're at the command line.
Why do you want to do this? Are you concerned at the time it takes to load your .emacs? If so, you might consider using the Emacs client/server instead.
I am not sure how to exit as well but..... I would rather advice another kind of logic for your init file than a flat file with all different configurations.
Take for example your ~/.emacs (or better ~/.emacs.d/init.el) as your controller and files like ~/.emacs.d/aquamacs.el or ~/.emacs.d/textmode.el as your individual configuration files.
That would make your init having something like this :
(defun my-short-hostname()
(string-match "[0-9A-Za-z]+" system-name)
(substring system-name (match-beginning 0) (match-end 0))
)
;Load different config file in text mode or gui mode.
(if (null window-system)
(load-file "~/.emacs.d/texmode-emacs.el")
(load-file "~/.emacs.d/gui.el"))
;Load configuration for this host only, ie ~/.emacs.d/myhostname.el if exist
(if (file-exists-p
(downcase (concat "~/.emacs.d/" (my-short-hostname) ".el")))
(load-file (downcase "~/.emacs.d/" (my-short-hostname) ".el"))))
I suggest having specific, different files to load conditionally from your .emacs, one for one setup, another for another setup.
Alternatively, just wrap the code for each setup in a progn and do the conditional in place, in .emacs itself.

What are good practices to get GNU emacs and xemacs co-habitate

I would like to make a gradual switch from GNU Emacs to Xemacs. Are there tricks I can use to have the two play well?
Currently, I see the following issues:
xemacs alters .emacs
The two do not like each others .elc files.
Thanks!
Interesting, most appear to be moving in the other direction as I believe XEmacs to be fairly dormant (based on activity of the xemacs-announce list). Simple packages can co-exist, but many folks have given up making their packages work in both XEmacs and Emacs.
But, in answer to your question, to get your .emacs to work in both, I'd start writing a some routines to do function translation between the two. For example, at one point I needed this to get my .emacs to work in XEmacs:
(if (not (fboundp 'tags-table-files))
(defun tags-table-files ()
(tag-table-files tags-file-name)))
Other things were triggered on the Emacs variant, which I stored in a variable GNU:
(setq GNU (not (string-match "XEmacs\\|Lucid" (emacs-version))))
(if GNU
(do-emacs-thing)
(do-xemacs-thing))
I was keeping compiled .emacs files and did this:
(setq compiled-dot-emacs-name (format ".emacs-%d%s" emacs-major-version
(if GNU "" "X")))
Regarding compiled packages, I'd probably store all the .el files in one directory (say emacs-lisp), but have an xemacs variant (xemacs-lisp) with symlinks to the .el files. And then you just byte compile each directory from the appropriate Emacs variant, and make sure to have your load-path point to the right one.
The Emacs wiki has a page on Emacs versus XEmacs which might be a good starting point to figure out other tips to make them cohabitate. Specifically, there's a page for customizing both.
I don't use xemacs, but newer GNU emacs will check for .emacs.d/init.el as well, so maybe moving .emacs stuff to init.el makes sense. Additionally you can link it to .xemacs/init.el if you manage to keep your customization applicable for both.
There is also a discussion on what emacs to prefer on emacswiki.
I started a slow move from Xemacs to Emacs a while ago. I now use both on a daily basis. To make the transition smoother (one set of init files), I stole the following .emacs file from http://xemacs.seanm.ca/_emacs (but the link is now dead).
(setq user-init-file
(expand-file-name "init.el"
(expand-file-name ".xemacs" "~")))
(setq custom-file
(expand-file-name "custom.el"
(expand-file-name ".xemacs" "~")))
(if (file-exists-p user-init-file)
(load-file user-init-file))
(if (file-exists-p custom-file)
(load-file custom-file))
My ~/.xemacs/init.el starts off with:
(unless (boundp 'running-xemacs)
(defvar running-xemacs nil))
(setq load-path (cons "~/.elisp" load-path)) ; packages for both emacsen
(if running-xemacs
(setq load-path (cons "~/.elisp/xemacs" load-path)) ; packages for Xemacs only
(setq load-path (cons "~/.elisp/gnuemacs" load-path))) ; packages for Gnuemacs only
From then on it is pretty obvious what I have (the occasional (if running-xemacs) ...). I also deleted all the .elc files from ~/.elisp, but I presume that Trey Jackson's suggestion will work.
on modern systems i do not see the need for precompiled elisp files anymore. The benefit in looking and on the fly changing the .el-files is much more higher.
.emacs: put your own defines in .emacs_startup (or which name you prefere) and put all your gnu-enmacs stuff there and put a conditional load in your .emacs