Calling (require ...) on a MELPA installed package gives FlyCheck error "Cannot open load file" - emacs

I want to require some packages installed through MELPA so that i can access their variables and functions without getting "free variable" or "undefined function" warnings.
However, when I try to load a package it isn't found by Flycheck and i get a "Cannot open load file" error. It seems that the bytecode compiler doesn't read into the directory with the files installed by MELPA, but I don't know how to solve this.
I'm using Emacs 26.3 with Purcell's config that includes Flymake-Flycheck. This snippet covers the relevant parts of the init-elpa.el custom files where you can see the at the end that even if I install and then (require ...) a package it still is marked with an error by Flycheck.
;;; init-elpa.el --- Settings and helpers for package.el -*- lexical-binding: t -*-
(require 'package)
(require 'cl-lib)
;;; Install into separate package dirs for each Emacs version, to prevent bytecode incompatibility
(setq package-user-dir
(expand-file-name (format "elpa-%s.%s" emacs-major-version emacs-minor-version)
user-emacs-directory))
;;; Standard package repositories
(add-to-list 'package-archives '( "melpa" . "https://melpa.org/packages/") t)
(defun require-package (package &optional min-version no-refresh)
"Install given PACKAGE, optionally requiring MIN-VERSION.
If NO-REFRESH is non-nil, the available package lists will not be
re-downloaded in order to locate PACKAGE."
...)
(defun maybe-require-package (package &optional min-version no-refresh)
"Try to install PACKAGE, and return non-nil if successful.
In the event of failure, return nil and print a warning message.
Optionally require MIN-VERSION. If NO-REFRESH is non-nil, the
available package lists will not be re-downloaded in order to
locate PACKAGE."
...)
;;; Fire up package.el
(setq package-enable-at-startup nil)
(package-initialize)
(defvar sanityinc/required-packages nil)
(defun sanityinc/note-selected-package (oldfun package &rest args)
"If OLDFUN reports PACKAGE was successfully installed, note that fact.
The package name is noted by adding it to
`sanityinc/required-packages'. This function is used as an
advice for `require-package', to which ARGS are passed."
...)
(advice-add 'require-package :around 'sanityinc/note-selected-package)
(when (fboundp 'package--save-selected-packages)
(require-package 'seq)
(add-hook 'after-init-hook
(lambda ()
(package--save-selected-packages
(seq-uniq (append sanityinc/required-packages package-selected-packages))))))
;; READ HERE: now i try to install and require some packages.
(require-package 'fullframe)
(require-package 'evil)
(require 'fullframe) ;; Flycheck gives an ERROR: cannot open load file, files or directory does not exist
(require 'evil) ;; same as above
(require 'python) ;;this gives no error, since it's built-in i guess.
(provide 'init-elpa)
;;; init-elpa.el ends here
You can see that (package-initialize) is called so the load-path should be set. Also, I have flycheck-emacs-lisp-load-path set to 'inherit, which should mean that the bytecode compiler reads the same dirs as a normal emacs instance.
What should I do in order to make the bytecode compiler recognize my ELPA directory?

Check out flycheck-emacs-lisp-load-path variable
flycheck-emacs-lisp-load-path is a variable defined in ‘flycheck.el’.
... When set to ‘inherit’, use the ‘load-path’ of the current Emacs
session during syntax checking.
E.g you could do:
(use-package flycheck
:diminish ""
:custom
(flycheck-emacs-lisp-load-path 'inherit)
...

Related

Emacs definition is void: use-package

I have a problem. If I copy any official code to enable package such elpy into my configuration I get:
Symbol's function definition is void: use-package
(use-package elpy
:ensure t
:init
(elpy-enable))
Please put this before using use-package:
(require 'package) ; Bring in to the environment all package management functions
;; A list of package repositories
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")
("elpa" . "https://elpa.gnu.org/packages/")))
(package-initialize) ; Initializes the package system and prepares it to be used
(unless package-archive-contents ; Unless a package archive already exists,
(package-refresh-contents)) ; Refresh package contents so that Emacs knows which packages to load
;; Initialize use-package on non-linux platforms
(unless (package-installed-p 'use-package) ; Unless "use-package" is installed, install "use-package"
(package-install 'use-package))
(require 'use-package) ; Once it's installed, we load it using require
;; Make sure packages are downloaded and installed before they are run
;; also frees you from having to put :ensure t after installing EVERY PACKAGE.
(setq use-package-always-ensure t)

Emacs first boot won't install all packages from package-selected-packages

I've got this in my init.el:
(require 'package)
(package-initialize)
(setq package-enable-at-startup nil)
(setq package-archives '(("ELPA" . "http://tromey.com/elpa/")
("gnu" . "http://elpa.gnu.org/packages/")
("melpa" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; Bootstrapping use-package
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(eval-when-compile (require 'use-package))
(use-package use-package
:config
(setq use-package-always-ensure t))
As far as I understand, this should be good to install all the packaged listed in
'(package-selected-packages
(quote
(org org-plus-contrib org-ref techela tuareg haskell-mode gnuplot gnuplot-mode helm-ispell ac-ispell paredit ox-tufte auctex json org-grep iedit wgrep helm geiser slime-company company-jedi zzz-to-char rainbow-delimiters avy ivy projectile twittering-mode zerodark-theme pretty-mode flycheck-clang-analyzer flycheck-irony flycheck yasnippet company-c-headers company-shell company-irony irony irony-mode company-lua mark-multiple expand-region popup-kill-ring dmenu ido-vertical-mode ido-vertical ox-html5slide centered-window-mode htmlize ox-twbs diminish erc-hl-nicks symon rainbow-mode switch-window dashboard smex company sudo-edit emms magit org-bullets hungry-delete beacon linum-relative spaceline fancy-battery exwm use-package)))
which is inside my custom-set-variables. However, when I do a first-time, clean (no existing elpa/ directory) startup of Emacs reading this init.el, not all of the packages are gotten and installed. But then I can do a package-install-selected-packages and, Emacs reports that it doesn't have anything in package-selected-packages. Looking at the variable confirms this. What could be going wrong? An older "working" version of this (with existing elpa/ directory) responds oddly to package-install-selected-packages, wanting to install e.g., auctex and some nine other packages that the package code above apparently isn't seeing or dealing with. I'm baffled as to why package-selected-packages seems to be so flaky for me. I'm assuming my older .emacs.d with the existing elpa/ has install info that is "working around" this failing package-selected-packages situation.

Newly created Emacs init file won't load

Brand-new Emacs 24.5 64-bit install on Win7 did not seem to include an init.el file and I needed one for settings for a plug-in I want to use, so I created one in Emacs at C:\Users\brinklec\AppData\Roaming.emacs.d. Restarting Emacs, got the apparently famous
Warning (initialization): An error occurred while loading `c:/Users/brinklec/AppData/Roaming/.emacs.d/init.el':
File error: Cannot open load file, no such file or directory, use-package
I did not initially understand the reference to "use-package" at the end of the error, and the preceding wording apparently misled me to think it was init.el that Emacs was saying it c ould not load.
Manual load gives the same error. However, Emacs can open and successfully resave the file.
I saw a bunch of similar issues, but all seemed to involve other files referenced in an already existing and successfully loaded init.el. I thought my issue was different, but now maybe not?
Contents of my init.el come from recommended config for ENSIME plug-in (verbatim except for first comment line below):
;;; ~/.emacs.d/init.el
;; global variables
(setq
inhibit-startup-screen t
create-lockfiles nil
make-backup-files nil
column-number-mode t
scroll-error-top-bottom t
show-paren-delay 0.5
use-package-always-ensure t
sentence-end-double-space nil)
;; buffer local variables
(setq-default
indent-tabs-mode nil
tab-width 4
c-basic-offset 4)
;; modes
(electric-indent-mode 0)
;; global keybindings
(global-unset-key (kbd "C-z"))
;; the package manager
(require 'package)
(setq
use-package-always-ensure t
package-archives '(("gnu" . "http://elpa.gnu.org/packages/")
("org" . "http://orgmode.org/elpa/")
("melpa" . "http://melpa.org/packages/")))
(package-initialize)
(when (not package-archive-contents)
(package-refresh-contents)
(package-install 'use-package))
(require 'use-package)
Debug output from --debug-init:
Debugger entered--Lisp error: (file-error "Cannot open load file" "no such file or directory" "use-package")
require(use-package)
eval-buffer(#<buffer *load*> nil "c:/Users/brinklec/AppData/Roaming/.emacs.d/init.el" nil t) ; Reading at buffer position 841
load-with-code-conversion("c:/Users/brinklec/AppData/Roaming/.emacs.d/init.el" "c:/Users/brinklec/AppData/Roaming/.emacs.d/init.el" t t)
load("c:/Users/brinklec/AppData/Roaming/.emacs.d/init" t t)
#[0 "\205\262
Adding the following expression right before the final (require 'use-package) seems to have resolved the error (though I'm also no longer getting the helpful greeting screen on startup):
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))

Load and activate of Emacs package.el

I have something like (to be simplify)
(require 'package)
(setq package-archives
'(("org" . "http://orgmode.org/elpa/")
("melpa" . "http://melpa.org/packages/")
("melpa-stable" . "http://stable.melpa.org/packages/")
("gnu" . "http://elpa.gnu.org/packages/")))
(setq package-enable-at-startup nil)
(package-initialize t)
(unless (package-installed-p 'use-package)
(package-refresh-contents)
(package-install 'use-package))
(let ((default-directory (expand-file-name user-emacs-directory "elpa")))
(normal-top-level-add-subdirs-to-load-path))
(require 'use-package)
(use-package helm
:ensure t
:commands (helm-M-x
helm-mini
helm-find-files
helm-show-kill-ring)
:init
(add-hook 'after-init-hook 'helm-mode)
:config
(helm-autoresize-mode 1))
in my .emacs. But I was told that Symbol's function definition is void: helm-mode after startup emacs.
After reading the manual of Packaging Basics and this answer, I find I still don't understand the mechanism of package.el.
I notice that the words load and activate are used in the manual, I suppose that load is 'Emacs adds the package’s content directory to load-path, and evaluates the autoload definitions in name-autoloads.el.' and activate is to 'fully require'. I know if I change (package-initialize t) into (package-initialize) everything will be fine.
I confirm that something like "/Users/gaki/.emacs.d/elpa/helm-20160112.258" is in load-path and helm-mode is autoload. Isn't it can be autoload and even in the after-init-hook ?
A look at the code for package-activate and its helper package-activate-1 shows that a package's autoloads file is not loaded unless the package has been 'activated'.
You've told Emacs not to activate any packages by using (package-initialize t), and you've prevented it from activating them after loading your init file with (setq package-enable-at-startup nil), so none of your package autoloads are known to Emacs.
I suggest changing (package-initialize t) to (package-initialize).
Note that the documentation you linked to describes the NO-ACTIVATE argument as "for internal use only".
p.s. Activation does not require the package features -- there would be no purpose to the autoloads if it did -- so this should not take a very significant amount of time, unless perhaps you have a really large number of packages? What kind of time difference are you actually seeing here? (https://emacs.stackexchange.com/a/19263/454 may help with answering that.)

How to automatically install Emacs packages by specifying a list of package names?

I am using package to manage my Emacs extensions. In order to synchronize my Emacs settings on different computers, I'd like a way to specify a list of package names in .emacs file and then package could automatically search and install the packages, so that I don't need to install them manually by calling M-x package-list-packages. How to do that?
; list the packages you want
(setq package-list '(package1 package2))
; list the repositories containing them
(setq package-archives '(("elpa" . "http://tromey.com/elpa/")
("gnu" . "http://elpa.gnu.org/packages/")
("marmalade" . "http://marmalade-repo.org/packages/")))
; activate all the packages (in particular autoloads)
(package-initialize)
; fetch the list of packages available
(unless package-archive-contents
(package-refresh-contents))
; install the missing packages
(dolist (package package-list)
(unless (package-installed-p package)
(package-install package)))
Emacs 25.1+ will automatically keep track of user-installed packages in the customizable package-selected-packages variable. package-install will update the customize variable, and you can install all selected packages with the package-install-selected-packages function.
Another convenient advantage of this approach is that you can use package-autoremove to automatically remove packages that are not included in package-selected-packages (though it will preserve dependencies).
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
(package-install-selected-packages)
Source: http://endlessparentheses.com/new-in-package-el-in-emacs-25-1-user-selected-packages.html
Based on comments by Profpatsch and answers below:
(defun ensure-package-installed (&rest packages)
"Assure every package is installed, ask for installation if it’s not.
Return a list of installed packages or nil for every skipped package."
(mapcar
(lambda (package)
;; (package-installed-p 'evil)
(if (package-installed-p package)
nil
(if (y-or-n-p (format "Package %s is missing. Install it? " package))
(package-install package)
package)))
packages))
;; make sure to have downloaded archive description.
;; Or use package-archive-contents as suggested by Nicolas Dudebout
(or (file-exists-p package-user-dir)
(package-refresh-contents))
(ensure-package-installed 'iedit 'magit) ; --> (nil nil) if iedit and magit are already installed
;; activate installed packages
(package-initialize)
Here's the code I use for Emacs Prelude:
(require 'package)
(require 'melpa)
(add-to-list 'package-archives
'("melpa" . "http://melpa.milkbox.net/packages/") t)
(package-initialize)
(setq url-http-attempt-keepalives nil)
(defvar prelude-packages
'(ack-and-a-half auctex clojure-mode coffee-mode deft expand-region
gist haml-mode haskell-mode helm helm-projectile inf-ruby
magit magithub markdown-mode paredit projectile
python sass-mode rainbow-mode scss-mode solarized-theme
volatile-highlights yaml-mode yari yasnippet zenburn-theme)
"A list of packages to ensure are installed at launch.")
(defun prelude-packages-installed-p ()
(loop for p in prelude-packages
when (not (package-installed-p p)) do (return nil)
finally (return t)))
(unless (prelude-packages-installed-p)
;; check for new packages (package versions)
(message "%s" "Emacs Prelude is now refreshing its package database...")
(package-refresh-contents)
(message "%s" " done.")
;; install the missing packages
(dolist (p prelude-packages)
(when (not (package-installed-p p))
(package-install p))))
(provide 'prelude-packages)
If you're not using MELPA you don't need to require it (and if you do melpa.el has got to be on your load-path (or installed via MELPA). The package db is not refreshed each time (as this would slow down the startup significantly) - only where there are uninstalled packages present.
No one has mentioned Cask yet, but it is quite suitable for this task.
Basically you create ~/.emacs.d/Cask listing the packages you want to install. For example:
(source melpa)
(depends-on "expand-region")
(depends-on "goto-last-change")
; ... etc
Running cask from the command line will install these packages for you, and any dependencies they need.
Also, you can automatically update installed packages using cask update.
Call package-install with the package name as a symbol. You can find the package names for your packages by calling package-install interactively and completing on the name. The function package-installed-p will let you know if it's already been installed.
For example:
(mapc
(lambda (package)
(or (package-installed-p package)
(package-install package)))
'(package1 package2 package3))
(require 'cl)
(require 'package)
(setq cfg-var:packages '(
emmet-mode
ergoemacs-mode
flycheck
flycheck-pyflakes
monokai-theme
py-autopep8
py-isort
rainbow-mode
yafolding
yasnippet))
(defun cfg:install-packages ()
(let ((pkgs (remove-if #'package-installed-p cfg-var:packages)))
(when pkgs
(message "%s" "Emacs refresh packages database...")
(package-refresh-contents)
(message "%s" " done.")
(dolist (p cfg-var:packages)
(package-install p)))))
(add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/") t)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/") t)
(add-to-list 'package-archives '("melpa-stable" . "http://stable.melpa.org/packages/") t)
(add-to-list 'package-archives '("org" . "http://orgmode.org/elpa/") t)
(package-initialize)
(cfg:install-packages)
I like checking if the user wants to install the packages first as done in this answer. Also I'm refreshing my package contents once before installing anything. I'm not sure if this is the best way, but I don't think the top answers were doing it for me.
(setq required-pkgs '(jedi flycheck cider clojure-mode paredit markdown-mode jsx-mode company))
(require 'cl)
(setq pkgs-to-install
(let ((uninstalled-pkgs (remove-if 'package-installed-p required-pkgs)))
(remove-if-not '(lambda (pkg) (y-or-n-p (format "Package %s is missing. Install it? " pkg))) uninstalled-pkgs)))
(when (> (length pkgs-to-install) 0)
(package-refresh-contents)
(dolist (pkg pkgs-to-install)
(package-install pkg)))
Here's mine, it's shorter :)
(mapc
(lambda (package)
(unless (package-installed-p package)
(progn (message "installing %s" package)
(package-refresh-contents)
(package-install package))))
'(browse-kill-ring flycheck less-css-mode tabbar org auto-complete undo-tree clojure-mode markdown-mode yasnippet paredit paredit-menu php-mode haml-mode rainbow-mode fontawesome))
I ran into a problem that nothing happened after adding (package-install 'org) into .emacs. I wanted to install the up-to-date version of org-mode and the built-in org-mode is quite old.
I dug out the source code of package-install from Emacs 25.3.1. The function self already checks if a package is installed or not and refuses to install it if the package is already installed. So the check (unless (package-installed-p package) ...) from answer 10093312 is in fact uncalled for.
(defun package-install (pkg &optional dont-select)
"Install the package PKG.
PKG can be a package-desc or a symbol naming one of the available packages
in an archive in `package-archives'. Interactively, prompt for its name.
If called interactively or if DONT-SELECT nil, add PKG to
`package-selected-packages'.
If PKG is a package-desc and it is already installed, don't try
to install it but still mark it as selected."
(interactive
(progn
;; Initialize the package system to get the list of package
;; symbols for completion.
(unless package--initialized
(package-initialize t))
(unless package-archive-contents
(package-refresh-contents))
(list (intern (completing-read
"Install package: "
(delq nil
(mapcar (lambda (elt)
(unless (package-installed-p (car elt))
(symbol-name (car elt))))
package-archive-contents))
nil t))
nil)))
(add-hook 'post-command-hook #'package-menu--post-refresh)
(let ((name (if (package-desc-p pkg)
(package-desc-name pkg)
pkg)))
(unless (or dont-select (package--user-selected-p name))
(package--save-selected-packages
(cons name package-selected-packages)))
(if-let ((transaction
(if (package-desc-p pkg)
(unless (package-installed-p pkg)
(package-compute-transaction (list pkg)
(package-desc-reqs pkg)))
(package-compute-transaction () (list (list pkg))))))
(package-download-transaction transaction)
(message "`%s' is already installed" name))))
The built-in org-mode also counts as installed and package-install refuses to install the newer version from ELPA. After spending some time reading package.el, I came up with the following solution.
(dolist (package (package-compute-transaction
() (list (list 'python '(0 25 1))
(list 'org '(20171211)))))
;; package-download-transaction may be more suitable here and
;; I don't have time to check it
(package-install package))
The reason why it works is that package-* family functions handle the arguments differently based on whether if it is a symbol or a package-desc object. You can only specify version info for package-install via a package-desc object.
Here's another way.
;; assure every package is installed
(defun ensure-package-installed (&rest packages)
(let ((user-required-packages
(seq-remove
(lambda (package) (package-installed-p package))
packages)))
(when user-required-packages
(package-refresh-contents)
(dolist (package user-required-packages)
(package-install package)))))
;; list of packages to install
(ensure-package-installed
'try
'which-key)
Close to Nicholas's answer:
Packages package-1, package-2, and package-3 are installed if they're not present locally. If they are present, Emacs loads without any delay.
(setq package-archives ;
'(("gnu" . "https://elpa.gnu.org/packages/") ; declare repositories
("melpa" . "https://melpa.org/packages/"))) ;
(require 'package) ; activate packages
(package-initialize) ; initialize package facility
(setq my-packages
'(package-1
package-2
package-3))
(unless package-archive-contents ; unless packages are not available locally, dont refresh package archives
(package-refresh-contents)) ; refreshing package contents is time-consuming and should be done on demand
(dolist (pkg my-packages) ;
(unless (package-installed-p pkg) ; iterate over packages and install missing ones
(package-install pkg))) ;
;; other config below