Customize the list of packages that emacs-prelude provides - emacs

I see at this link how emacs prelude ensures that a set of packages is installed when emacs starts. I was wondering if I could somehow extend the variable prelude-packages to add some other packages, without changing the prelude-packages.el file?
Barring that I was wondering how I could define a list of packages that are installed at start-up if they aren't currently installed.

You can place a .el file in personal/ directory in Prelude. Prelude loads any .el file it finds there in an alphabetical order. Below is the content of my personal/00-packages.el file.:
(require 'package)
(add-to-list 'package-archives
'("marmalade" .
"http://marmalade-repo.org/packages/"))
(package-initialize)
;; My packages
(setq prelude-packages (append '(
drupal-mode
nginx-mode
) prelude-packages))
;; Install my packages
(prelude-install-packages)
"00" is added to the file name to ensure that the file is loaded before all personal customizations. Add any new package you need to the list being appended to prelude-packages.
Also, if you want to use any mode that is not available in MELPA or Marmalade, you can simply drop the mode's file in personal folder and Prelude will pick it up while loading. If there are any customizations to that mode, simply create another .el file and add the Emacs Lisp code there.

Prelude recommends to use
(prelude-require-packages '(some-package some-other-package))
if you have several package. Or in case you want to add just one package:
(prelude-require-package 'some-package)
If you want you can still maintain your package list in a variable:
(setq my-packages '(drupal-mode nginx-mode toto-mode)
(prelude-require-package my-packages)

In your .emacs file you could add code like this (very similar to the code in the link you sent) to check if each package is installed and install it if is not:
(dolist (package '(eredis anything erlang elnode))
(unless (package-installed-p package)
(package-install package)))
In answer to your question there's no reason you can't do this after the prelude code has run.

Related

I can't load an .el package on emacs

So I downloaded an .el file, I put it on the ~/.emacs.d/elpa/ folder, but it won't appear on the M-x list-packages. How do I make it appear there or how can I install this file/package?
There are two ways of installing an Emacs package: either type M-x list-packages and install it from the list, letting Emacs download it for you, or download the package yourself and install it with M-x package-install-file.
Installing from a package archive
In the first case, note that there are several different package archives. The default value for the variable package-archives only contains GNU ELPA, but most people want to add MELPA to that list since it has more packages. To do that, you need to add the following to your .emacs file (copied from the MELPA web page):
(require 'package) ;; You might already have this line
(add-to-list 'package-archives
'("melpa" . "https://melpa.org/packages/"))
(when (< emacs-major-version 24)
;; For important compatibility libraries like cl-lib
(add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/")))
(package-initialize) ;; You might already have this line
After that, typing M-x list-packages should list more packages than you'll ever need :)
Installing from a downloaded file
There are two types of packages: single-file packages and multi-file packages. The former can be downloaded as a single .el file, while the latter are distributed as tarballs (.tar). Both types can be installed with M-x package-install-file.
Note that not every .el file can be installed as a package. The comments at the beginning of the file need to follow a certain convention, documented in the Simple packages node of the Emacs Lisp reference manual.
That leaves the possibility that the .el file you've downloaded is not installable as a package. In that case, you should put it in some other directory (~/.emacs.d/elpa is meant for installed packages only), add that directory to the load-path variable, and require the package. If you have foo.el and put it in ~/path/to/foo, it would look something like this:
(add-to-list 'load-path "~/path/to/foo")
(require 'foo)
An .el file is not a package. Installing it via ELPA is probably vastly preferrable to manually downloading a static .el file; perhaps the maintainer has a home page with ELPA (or Marmalade, etc) instructions.
In particular, a package will receive updates as they are made available, so you will not be forever stuck on an increasingly obsolete, unmanaged version (though quiet, fully automatic updates are not yet available or feasible, AFAICT).
But if you have to get by with just the file you already downloaded, you can put it pretty much anywhere you like, as long as that directory is included in the load-path. Manually mucking with the elpa directory is a bad idea, though; put it somewhere else.
Look for comments near the top of the file for any additional instructions; any autoloads, for example, will probably have to be configured separately, and usually completely manually.
This used to be how you always did things in older versions of Emacs, so you should find that the Internet is still practically bulging with guides and tutorials which explain the finer details of this mechanism, if this answer alone isn't sufficient.

How do I automatically (re)compile ELPA packages?

I'm now installing as much as I can through MELPA and Marmalade, and I manage my ~/.emacs.d using git. However, I have git ignore *.elc files.
This means that when I install a package on one system and then start using another system, git pull only gives me the *.el files. Using these files is often slower than using *.elc.
I tried adding the following to ~/.emacs.d/init.el:
;; load the packages we've installed. Note that package-install
;; byte-compiles the packages, but .elc is ignored by git so we force recompilation here
(byte-recompile-directory (expand-file-name "~/.emacs.d/elpa") 0)
(package-initialize)
Unfortunately, this isn't equivalent to the compilation done by package.el. For example, if I install emacs-eclim, package.el doesn't compile emacs-eclim/company-emacs-eclim.el, and I get the following error:
Leaving directory `/home/wilfred/.emacs.d/elpa'
Compiling file /home/wilfred/.emacs.d/elpa/emacs-eclim-20130310.1237/company-emacs-eclim.el at Mon Mar 11 15:40:01 2013
Entering directory `/home/wilfred/.emacs.d/elpa/emacs-eclim-20130310.1237/'
company-emacs-eclim.el:35:1:Error: Cannot open load file: eclim
Warning: reference to free variable `multiple-cursors-mode'
Warning: reference to free variable `mc--read-char'
Warning: assignment to free variable `mc--read-char'
Warning: reference to free variable `multiple-cursors-mode'
Warning: reference to free variable `mc--read-quoted-char'
Warning: assignment to free variable `mc--read-quoted-char'
Warning: reference to free variable `rectangular-region-mode'
Warning: reference to free variable `rectangular-region-mode'
How do I make Emacs byte-compile only the same files as package.el would?
package.el actually uses exactly the same method, it's just recompiling on startup makes the errors more noticable.
The function used is package--make-autoloads-and-compile, which calls:
(byte-recompile-directory pkg-dir 0 t)
So the original code in the question is correct. However, to recompile a directory that isn't yet compiled, you can do the following:
(require 'dash)
(require 'f)
(defun was-compiled-p (path)
"Does the directory at PATH contain any .elc files?"
(--any-p (f-ext? it "elc") (f-files path)))
(defun ensure-packages-compiled ()
"If any packages installed with package.el aren't compiled yet, compile them."
(--each (f-directories package-user-dir)
(unless (was-compiled-p it)
(byte-recompile-directory it 0))))
(ensure-packages-compiled)
I recommend not keeping the packages in version control (you wouldn't put .o files under revision control, would you?). Here is the code I use to keep my packages in sync:
(setq jpk-packages
'(
ac-dabbrev
...
yasnippet
))
(package-initialize)
(add-to-list 'package-archives
'("melpa" . "http://melpa.milkbox.net/packages/"))
(add-to-list 'package-archives
'("org" . "http://orgmode.org/elpa/"))
(when (not package-archive-contents)
(package-refresh-contents))
(dolist (pkg jpk-packages)
(when (and (not (package-installed-p pkg))
(assoc pkg package-archive-contents))
(package-install pkg)))
(defun package-list-unaccounted-packages ()
"Like `package-list-packages', but shows only the packages that
are installed and are not in `jpk-packages'. Useful for
cleaning out unwanted packages."
(interactive)
(package-show-package-list
(remove-if-not (lambda (x) (and (not (memq x jpk-packages))
(not (package-built-in-p x))
(package-installed-p x)))
(mapcar 'car package-archive-contents))))
I put the above in init.el (which of course is under version control), and it installs any packages that don't exist yet when emacs starts up. Updating is done from the buffer package-list-packages creates. package-list-unaccounted-packages shows all the packages that are installed but not in my jpk-packages list, and makes it easy to remove the ones that I took out of the list.
To answer your specific question, I'd just delete the elpa directory and reinstall everything (using the above code).
The solution I like to the more general question of "How do I automatically re-compile any outdated .elc file" is to use https://github.com/tarsius/auto-compile
I used to have a handful of custom solutions which covered most situations I ran into, but this library covers everything I was doing and more besides. Just initialise it before loading anything else, and you're sorted.
As to the original question of not compiling files which were not originally compiled, that's what the 0 argument to byte-recompile-directory does, so you're explicitly asking for that behaviour. The default behaviour is to only recompile existing outdated .elc files, so you should simply remove that 0.
I do not know the answer to your specific issue about byte-compiling packages exactly the same way package.el would.
However, for your more general problem about maintaining your emacs configuration directory in git while installing extensions through Melpa or marmalade, I suggest you give a look to pallet, which has been designed to solve this very problem.
(byte-compile-file) worked for me when I need to manually recompile packages I have previously installed using elpa.
Particularly for this situation: https://github.com/yjwen/org-reveal/issues/76t
The problem you have is simply that you byte-compile files before initializing your packages. If you switch the two lines, your problem should disappear. The error you get (Cannot open load file: eclim) is because ~/.emacs.d/elpa/emacs-eclim-20130310.1237/ is not yet in your load-path, and package-initialize will add it to your load-path (along with a few other things).

Configuring auto-complete when it is installed as a package

I used to have the following line in auto-complete:
(require 'auto-complete-config)
(add-to-list 'ac-dictionary-directories "~/.emacs.d/auto-complete/dict")
(ac-config-default)
but now that I installed auto-complete as an Emacs package, I don't have an auto-complete folder in my .emacs.d directory anymore, so the second line above does not work.
This leads me to two questions:
More generally, where are packages installed?
How should I adapt my add-to-list line now that I have auto-complete installed as a package?
By default (in newer versions of auto-complete) the directory used will the the one in the site-lisp folder where emacs installed the package so that line is not required. Simply placing
(setq-default ac-sources
'(ac-source-abbrev ac-source-dictionary
ac-source-words-in-same-mode-buffers))
In your .emacs will let auto-complete know the sources you want for completion and the dictionary file will be placed appropriately.
If you want a custom dictionary (at least what I did) was
(add-to-list 'ac-dictionary-directiories "~/.dict")
Just make sure the directory you put exists.
EDIT: Forgot to mention that this is only if you want to add custom dictionaries to auto-complete (Java object higlighting or custom keywords, etc...). The language ones are enabled by default.

How do I check if emacs has a library installed?

I want to check whether pymacs has been installed.
M-x locate-library will tell you if emacs can find the library in its load-path. If it does not return anything you might need to edit your load-path first.
There are many ways to do it.
type apropos, then pymacs. If it finds the symbols, it was loaded.
(require 'pymacs) -- if it does not return error, it was loaded
if you already loaded it, it called (provide 'pymacs), and the variable load-history keeps the symbols
There are still other ways to ckeck it.
Not sure if you're talking about ELPA packages, but I have the following definitions in my .emacs:
(defun sh-elpa-ensure-package (name)
"Make sure that a particular package is installed; if not then
automatically download, compile and install it.
This is primarily used by sh-elpa-require to allow deployment of
the configuration to a new machine - packages will therefore be
downloaded on that fresh machine (following installation they are
automatically kept up to date by the package manager).
Use this as follows:
(sh-elpa-ensure-package 'org)"
(if (not (package-installed-p name))
(package-install name)))
(defun sh-elpa-require (name)
"A replacement for the standard Emacs 'require'
function. This uses sh-elpa-require to download and install a
package if necessary prior to using the standard 'require'
function to import it. This is useful to allow the configuration
to just 'sh-elpa-require' a package and not have to bother
checking whether it has been installed yet."
(sh-elpa-ensure-package name)
(require name))
I can then include code such as the following in my .emacs to activate the package - if it's not already installed then this will download it from ELPA and byte-compile it before it is "required":
(sh-elpa-require 'pymacs)
If you're just talking about checking whether a package is installed from elisp, then you can also pick the bones of that out of the above snippet - see the (if (not (package-installed-p name)) bit.

How to install a Emacs plugin (many times it's a .el file) on Windows platform?

I'm new to Emacs. I found many emacs plugins are released as an .el file. I'm not sure how to install them. Can I just put them in my emacs installation directory?
After placing it, say myplugin.el to your ~/.emacs.d/ directory, add the following in your .emacs file:
(add-to-list 'load-path "~/.emacs.d/")
(load "myplugin.el")
Also, in many cases you would need the following instead of the second line:
(require 'myplugin)
In any case, you should consult the documentation of the package you are trying to install on which one you should use.
If you are unsure where your ~ directory is, you may see it by typing C-x d ~/ and pressing Enter.
As already stated, you'll need the location of the file to be in Emacs' load path.
Read the comments at the top of the file to see if it has any particular installation or usage instructions. Authors often provide this information, and there isn't one single correct way to do it, so it's sensible to look.
Failing that, if the file contains a (provide 'some-name) line (typically at the end of the file), then you would be expected to use (require 'some-name) to load it.
You may also wish to byte-compile the library for speed (but that's a different question).
Many times, an emacs plugin will consist of a directory of elisp files that need to be accessible from the load path. A simple way to ensure that all individual elisp files as well as subdirectories of elisp files are included in the load path and accessible is to do something similar to the following:
Create a directory called ~/.emacs.d/site-lisp.
Install any single elisp files in the ~/.emacs.d/site-lisp directory.
Install any packages that consist of multiple elisp files in a subdirectory under your ~/.emacs.d/site-lisp directory.
Add the following code to your ~/.emacs file to ensure that Emacs "sees" all the elisp files that you have installed:
(add-to-list 'load-path "~/.emacs.d/site-lisp")
(progn (cd "~/.emacs.d/site-lisp")
(normal-top-level-add-subdirs-to-load-path))
This will ensure that all elisp files that are located either in either the ~/.emacs.d/site-lisp directory or in a subdirectory under that directory are accessible.
Some supplementary information:
MATLAB.el comes from http://matlab-emacs.sourceforge.net/
On windows, use the load path that looks like this:
(add-to-list 'load-path' "C:\\Dropbox\\Portable\\emacs\\matlab-emacs")
If you want FULL MATLAB functionality you should use:
;;MATLAB Mode:
(add-to-list 'load-path' "C:\\Dropbox\\Portable\\emacs\\matlab-emacs")
(require 'matlab-load)
if you just want to edit text files:
;;MATLAB Mode:
(add-to-list 'load-path' "C:\\Dropbox\\Portable\\emacs\\matlab-emacs")
(autoload 'matlab-mode "matlab" "Enter MATLAB mode." t)
(setq auto-mode-alist (cons '("\\.m\\'" . matlab-mode) auto-mode-alist))
(autoload 'matlab-shell "matlab" "Interactive MATLAB mode." t)