elisp warning "reference to free variable" - emacs

I am wandering how to get rid of the elisp warning.
my setup is the following:
I have init.el file which sets "emacs-root" variable:
;; root of all emacs-related stuff
(defvar emacs-root
(if (or (eq system-type 'cygwin)
(eq system-type 'gnu/linux)
(eq system-type 'linux)
(eq system-type 'darwin))
"~/.emacs.d/" "z:/.emacs.d/"
"Path to where EMACS configuration root is."))
then in my init.el I have
;; load plugins with el-get
(require 'el-get-settings)
in el-get-settings.el I am loading packages with el-get and appending "el-get/el-get" folder to the load-path:
;; add el-get to the load path, and install it if it doesn't exist
(add-to-list 'load-path (concat emacs-root "el-get/el-get"))
the problem is that I have a lips warning on 'emacs-root'
in last expression for add-to-list : "reference to free variable 'emacs-root'"
what am I doing wrong here and is there any way to make the compiler happy?
this setup works ok btw - I don't have any issues during load time, just this annoying warning.
Regards, Roman

When you are compiling the file where you reference the variable emacs-root, the variable must be already defined.
The easiest way to avoid the warning is to add
(eval-when-compile (defvar emacs-root)) ; defined in ~/.init.el
in el-get-settings.el before the offending form.
Alternatively, you can move the defvar from init.el to el-get-settings.el.
Note that you can use eval-when-compile in defvar to speed-up loading the compiled file (of course, if you do that, you should not copy the compiled file between platforms):
(defvar emacs-root
(eval-when-compile
(if (or (eq system-type 'cygwin)
(eq system-type 'gnu/linux)
(eq system-type 'linux)
(eq system-type 'darwin))
"~/.emacs.d/"
"z:/.emacs.d/"))
"Path to where EMACS configuration root is.")
Note also that your original defvar emacs-root in the question if broken, it sets the variable emacs-root to "Path to where EMACS configuration root is." on windows.

Related

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

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)
...

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.)

error: package.el not yet initialized

I'm in the middle of organising my .emacs file to better keep track of all the things I'm adding to it.
In doing so I've run into the error described in the title, and I'm not sure exactly why
Here's my .emacs file: (the load of comments are for my own reference)
;;;; Emacs config file
;; convenience function for loading multiple libs in a single call
(defun load-libs (&rest libs)
(dolist (lib libs)
(load-library lib)))
;; path to custom libraries as well as the libraries themselves
(add-to-list 'load-path "~/.emacs.d/lisp/")
(load-libs "convenience" "editor-behaviour")
;; Add support for the package manager
(require 'package)
;; Add various package archives
(add-to-list 'package-archives
'("marmalade" . "http://marmalade-repo.org/packages/")
'("melpa" . "http://melpa.milkbox.net/packages/"))
;; Installs packages if they aren't already
(package-refresh-and-install ; from convenience.el
'scala-mode2 'sbt-mode 'haskell-mode 'geiser 'auto-complete 'ac-geiser 'cider)
;; Initialise packages
(package-initialize)
;; libs dependent on the packages being initialized go here
(load-library "autocomplete-config")
;; Enable Haskell indentation
(custom-set-variables
'(haskell-mode-hook '(turn-on-haskell-indentation)))
Running emacs .emacs --debug-init gives me the following output:
Debugger entered--Lisp error: (error "package.el is not yet initialized!")
signal(error ("package.el is not yet initialized!"))
error("package.el is not yet initialized!")
package-installed-p(scala-mode2)
(if (package-installed-p pkg) nil (package-refresh-contents) (package-install pkg))
(while --dolist-tail-- (setq pkg (car --dolist-tail--)) (if (package-installed-p pkg) $
(let ((--dolist-tail-- pkgs) pkg) (while --dolist-tail-- (setq pkg (car --dolist-tail-$
package-refresh-and-install(scala-mode2 sbt-mode haskell-mode geiser auto-complete ac-$
eval-buffer(#<buffer *load*> nil "/Users/ElectricCoffee/.emacs" nil t) ; Reading at $
load-with-code-conversion("/Users/ElectricCoffee/.emacs" "/Users/ElectricCoffee/.emacs$
load("~/.emacs" t t)
#[0 "^H\205\262^# \306=\203^Q^#\307^H\310Q\202;^# \311=\204^^^#\307^H\312Q\202;^#\$
command-line()
normal-top-level()
Which suggests (by my understanding) that it has something to do with convenience.el, but all that's in there is this:
(defun package-refresh-and-install (&rest pkgs)
"Utility function to refresh package contents and install several packages at once"
(dolist (pkg pkgs)
(unless (package-installed-p pkg)
(package-refresh-contents)
(package-install pkg))))
So I'm not exactly sure where I'm making an error here... Any help?
You need to call package-initialize before you call package-refresh-and-install.

share emacs configuration between emacs 23 and emacs 24

I'm trying to put all my emacs configuration under version control in order to easily switch between different computers. Actually my preferred system is OSX (10.8.3) with emacs 24.3 from http://emacsformacosx.com/. But I can also work in other systems (more likely linux-based although different distribution ubuntu/scientific-linux) which generally are equipped with emacs 23.4. What I would like to have is a init file which check the version of emacs and the operating system, load the needed packages from emacs package manager.
So far my .emacs init file for emacs 24.3 on OSX is as follow
(require 'package)
(setq package-archives '(
("marmalade" . "http://marmalade-repo.org/packages/")
("org" . "http://orgmode.org/elpa/")
("melpa" . "http://melpa.milkbox.net/packages/")))
(package-initialize)
After that there are configuration (loaded separately as for example
(load "python-sy")
which uses some packages not installed as default: in particular
color-theme
org-mode
theme-changer
ess-site
magit
auctex
python.el (fgallina implementation)
plus some other things which relies in already built-in packages
I admit that I have no idea on how to start for having a .emacs init file which could be used indifferently in all the devices. Furthermore I also would like to have a way to load url-proxy-services based on the system configuration
(setq url-proxy-services '(("http" . "proxy.server.com:8080")))
Thank you for any help
Relevant variables are system-type and emacs-major-version. You can use something like the following
(if (>= emacs-major-version 24)
(progn
;; Do something for Emacs 24 or later
)
;; Do something else for Emacs 23 or less
)
(cond
((eq system-type 'windows-nt)
;; Do something on Windows NT
)
((eq system-type 'darwind)
;; Do something on MAC OS
)
((eq system-type 'gnu/linux)
;; Do something on GNU/Linux
)
;; ...
(t
;; Do something in any other case
))
Along with giornado answer, you can also put your package-specific settings in a way they will be evaluated only when the package is present by testing the (require) result. Example with the bbdb package:
(when (require 'bbdb nil t)
(progn ...put your (setq) and other stuff here... ))
For this situation I define few constants at the top of .emacs:
(defconst --xemacsp (featurep 'xemacs) "Is this XEmacs?")
(defconst --emacs24p (and (not --xemacsp) (>= emacs-major-version 24)))
(defconst --emacs23p (and (not --xemacsp) (>= emacs-major-version 23)))
(defconst --emacs22p (and (not --xemacsp) (>= emacs-major-version 22)))
(defconst --emacs21p (and (not --xemacsp) (>= emacs-major-version 21)))
Example usage:
(when --emacs24p
(require 'epa-file)
(epa-file-enable)
(setq epa-file-cache-passphrase-for-symmetric-encryption t) ; default is nil
)
Or:
(if --emacs22p
(c-toggle-auto-newline 1)
(c-toggle-auto-state 1))
etc.