I have installed some packages by using elpa in my Emacs, but how are they loaded when launching Emacs?
package-install is a part of package.el -- which You can see with describe-function. From package.el documentation:
;; At activation time we will set up the load-path and the info path,
;; and we will load the package's autoloads. If a package's
;; dependencies are not available, we will not activate that package.
So in every package there's a file
NAME-autoloads.el
and this file is loaded at start up.
The whole package is contained under the package-user-dir:
(setq package-user-dir "~/.emacs.d/site-lisp/package-install")
(require 'package)
Each package also contains NAME-pkg.el with package version and description. For example here're files related to tabbar package:
package-install # that's my package-user-dir
└── tabbar-2.0.1 # each package dir is in the separate dir
├── tabbar-autoloads.el # this file is loaded at start up
├── tabbar.el # the package itself. In this case it is just a single file
└── tabbar-pkg.el # information about the package for package managment
To quote the manual: 39.1.1 Summary: Sequence of Actions at Startup:
15. If package-enable-at-startup is non-nil, it calls the function package-initialize to activate any optional Emacs Lisp package that has been installed.
package-initialize is then calls package-activate which in turn calls package-activate-1 which ends with loading NAME-autoload.el:
(load (expand-file-name (concat name "-autoloads") pkg-dir) nil t)
Related
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)
...
First, please know that I am a beginner with Dune and project management in Ocaml. Nevertheless, I have installed Dune and created a new Dune-project which deals with camlimages library, graphics, etc. Project compilation and execution works well when i do the usual:
opam exec dune build
opam exec dune exec ./myexecutable.exe
However, I can't use Tuareg Mode in emacs because the latter doesn't seem to find/understand well the dune-project configuration file standing for the former ".merlin" before dune v2.8 (according to the doc: https://dune.readthedocs.io/en/latest/usage.html?highlight=merlin). That implies lot of "unbound modules" errors when I try to launch the current .ml into the Tuareg repl.
I've tried to add packages manually with
Merlin > Select packages
but Merlin does not seem to care about this, even though it appears in the merlin configuration file.
Some hypothesis:
Every time I want to access external "opam-installed" library/packages from dune, I need to launch Dune from Opam in order to access them instead of launching a simple "Dune" command into the shell. I feel the "Opam environment" is not accessible from the "shell environment". Does that play a role in my problem?
You could find some relevant information below, which might be useful to understand my problem:
Merlin > Check configuration without adding packages manually
Loaded .merlin files: /home/erwan/Bureau/Nextcloud/GIT/Projet_integrateur_L3OPTIM/dev/importimg/dune-project
Custom buffer settings:
-packages: none
-flags: ""
-extensions: none
Custom merlin setup: ((env "PATH=/home/erwan/.opam/default/bin") (command . "/home/erwan/.opam/default/bin/ocamlmerlin"))
Dune file
(executable
(name importimg)
(libraries camlimages.core camlimages.png graphics camlimages.graphics))
Snippet of code + Typical error i get from the REPL
Tree structure of my project (as generated by dune)
.
├── _build
│ ├── default
│ │ ├── dune
│ │ ├── dune-project
│ │ ├── image.png
│ │ ├── importimg.exe
│ │ └── importimg.ml
│ └── log
├── dune
├── dune-project
├── image.png
├── #importimg.ml#
└── importimg.ml
.emacs content
;; Basic .emacs with a good set of defaults, to be used as template for usage
;; with OCaml and OPAM
;;
;; Author: Louis Gesbert <louis.gesbert#ocamlpro.com>
;; Released under CC0
;; Generic, recommended configuration options
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(ac-use-fuzzy nil)
'(backup-directory-alist (quote (("." . "~/.local/share/emacs/backups"))))
'(compilation-context-lines 2)
'(compilation-error-screen-columns nil)
'(compilation-scroll-output t)
'(compilation-search-path (quote (nil "src")))
'(custom-enabled-themes (quote (tango-dark)))
'(electric-indent-mode nil)
'(indent-tabs-mode nil)
'(line-move-visual t)
'(next-error-highlight t)
'(next-error-highlight-no-select t)
'(next-line-add-newlines nil)
'(require-final-newline t)
'(sentence-end-double-space nil)
'(show-paren-mode t)
'(show-trailing-whitespace t)
'(visible-bell t))
;; ANSI color in compilation buffer
(require 'ansi-color)
(defun colorize-compilation-buffer ()
(toggle-read-only)
(ansi-color-apply-on-region (point-min) (point-max))
(toggle-read-only))
(add-hook 'compilation-filter-hook 'colorize-compilation-buffer)
;; Some key bindings
(global-set-key [f3] 'next-match)
(defun prev-match () (interactive nil) (next-match -1))
(global-set-key [(shift f3)] 'prev-match)
(global-set-key [backtab] 'auto-complete)
;; OCaml configuration
;; - better error and backtrace matching
(defun set-ocaml-error-regexp ()
(set
'compilation-error-regexp-alist
(list '("[Ff]ile \\(\"\\(.*?\\)\", line \\(-?[0-9]+\\)\\(, characters \\(-?[0-9]+\\)-\\([0-9]+\\)\\)?\\)\\(:\n\\(\\(Warning .*?\\)\\|\\(Error\\)\\):\\)?"
2 3 (5 . 6) (9 . 11) 1 (8 compilation-message-face)))))
(add-hook 'tuareg-mode-hook 'set-ocaml-error-regexp)
(add-hook 'caml-mode-hook 'set-ocaml-error-regexp)
;; ## added by OPAM user-setup for emacs / base ## 56ab50dc8996d2bb95e7856a6eddb17b ## you can edit, but keep this line
(require 'opam-user-setup "~/.emacs.d/opam-user-setup.el")
;; ## end of OPAM user-setup addition for emacs / base ## keep this line
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
)
Versions
Merlin: 3.7.0
Dune: 2.1.3
Emacs: GNU Emacs 26.3 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.24.14) of 2020-03-26, modified by Debian
Opam: 2.0.5
Ocaml: 4.08.1
Thanks in advance
I have finally solved my problem in setting-up an "opam switch" into my working directory (WD). Once you are into your WD you have to launch the following command:
opam switch create . ocaml-base-compiler
Then, I reinstalled all the needed packages. Utop surprisingly replaced ocaml REPL in emacs ^^' (but i don't mind too much...). Now, dune and merlin "see" the packages.
Nevertheless, this tutorial helped me providing you this answer; https://ocamlverse.github.io/content/quickstart_ocaml_project_dune.html
(Please note that opam, emacs and utop were already installed on my working environment).
I'm new to Common Lisp, I'm using Emacs/SLIME on Windows 10, and I'm trying to wrap my head around how CL and ASDF/packaging works.
I have a custom package 'my-pack' in a directory 'D:\Dropbox\my-packages'.
I have created a .conf file in:
%LOCALAPPDATA%\config\common-lisp\source-registry.conf.d\
And added this line:
(:tree "D:\\Dropbox\\my-packages\\")
I opened Emacs, started SLIME and made the project via the REPL:
(cl-project:make-project #p"D:/Dropbox/my-packages/my-pack)
I verified that the project is in the directory and then loaded the system with asdf (version 3.3.1):
(asdf:load-system :my-pack)
And it worked fine.
But when I quit and restart Emacs, I get the following error when trying to the load the system:
Component :MY-PACK not found
[Condition of type ASDF/FIND-COMPONENT:MISSING-COMPONENT]
As far as I can tell I've followed the steps in the manual. Any help appreciated.
cl-project's make-project ends with this line:
(push dir asdf:*central-registry*)
it adds your new project's directory to this list that tells ASDF where to look for projects. What is its value when you restart CL?
2.
\config\common-lisp\
Shouldn't it be .config?
However, I don't encourage to use this conf file with :tree. The doc says:
tell ASDF to recursively scan all the subdirectories
So, imagine that just once, you try yourself at web development and you install, for example, JavaScript dependencies with npm or equivalent, you'll end up with a gigantic node_modules/ and your Lisp will now take a few seconds to start up.
I suggest to put your projects under ~/common-lisp/ or ~/quicklisp/local-projects, or to create symlinks, or to add yourself your projects in asdf:*central-registry* from your Lisp startup file:
;; .sbclrc
(pushnew "/home/me/projects/ciel/" asdf:*central-registry* :test #'equal)
I'm making a web application. Consider such structure
ProjectName/racket/Servlet.rkt
ProjectName/racket/chart/barchart/BarChart.rkt
ProjectName/template/barchart.svg
How can I inside the BarChart.rkt module require the Barchart.svg template, without using any ..? Ideally, if the application is launched from ProjectName (i.e. cd ProjectName; racket racket/Servlet.rkt), the require part would resemble (require "template/barchart.svg"), but use ProjectName as a root instead of the relative ProjectName/racket/barchart.
1) Naive method
You can use (define-runtime-path):
ProjectName/chart/barchart/BarChart.rkt:
#lang racket/base
(provide barchart-template)
(require
racket/runtime-path
racket/file)
(define-runtime-path barchart.svg "../../template/barchart.svg")
(define (barchart-template)
(file->string barchart.svg))
ProjectName/Servlet.rkt:
#lang racket/base
(require ProjectName/chart/barchart/Barchart)
(displayln (barchart-template)) ;; prints the content of the SVG file, wherever you are
2) Better method
Registering your package
From my experience, the best way to handle paths when developing a Racket application is making a package, then use the classic (require my-package/my-module) syntax instead of using relative paths.
For example, if you have a project like this:
ProjectName/Servlet.rkt
ProjectName/chart/barchart/BarChart.rkt
ProjectName/template/barchart.svg
By adding an info.rkt file at the root of your project, you transform it into a package.
echo "#lang info" > ProjectName/info.rkt
Then call cd ProjectName; raco pkg install.
Then you can require BarChart.rkt in any file with (require ProjectName/chart/BarChart).
Why am I telling you all this? Because now, you can start your application from any folder:
racket -l ProjectName/Servlet
Which will allow you to test easily if your paths are handled whatever the directory you are running the program in.
Getting rid of ../..
Now that your package is registered in your local database, you can easily find it's root directory using (pkg-directory) from pkg/lib:
ProjectName/chart/barchart/BarChart.rkt:
#lang racket/base
(provide barchart-template)
(require
racket/file
pkg/lib)
(define (barchart-template)
(define template.svg (build-path (pkg-directory "ProjectName")
"template/barchart.svg"))
(file->string template.svg))
I have a makefile in the project root directory. If I am editing a file in a subdirectory, how do I invoke make from EMACS? M-x compile make will not work as it looks for the makefile in the current directory. But I have the makefile in the project root directory.
Any thoughts?
Edit
As suggested, make -f fullpath_to_makefile did the trick. But I have some includes in the makefile like include "tests/module.mk" which failed. It is looking for "tests" directory in the subdirectory. This can be solved by specifying fully qualified path in the makefile. But I don't think that is a good solution. Any better approaches?
The M-x compile function looks up the compile-command-variable which you can override on the promt -- so just replace it with something like
(cd ../.. && make && cd -)
and let that run.
I also often use a file header (in line 1) such as
// -*- compile-command: "g++ -o myprog myprog.ccc -lfoo -lbar && ./myprog"; -*-
which you can generalize at will with different options. After reloading the file, M-x compile will execute your custom compile command which I find quite useful.
(I use scons, but the principle is the same. Change SConstruct to Makefile and scons to make...)
I've customized by .emacs so that it always compiles the project containing the current buffer's file, however deeply nested; it searches upwards for the first SConstruct and uses that as it's project root directory.
Here's a couple of functions which search up the directory hierarchy looking for SConstruct.
;; inspired by jds-find-tags-file in http://www.emacswiki.org/emacs/EmacsTags
(defun find-sconstruct ()
"recursively searches upwards from buffer's current dir for file named SConstruct and returns that dir. Or nil if not found or if buffer is not visiting a file"
(labels
((find-sconstruct-r (path)
(let* ((parent (file-name-directory path))
(possible-file (concat parent "SConstruct")))
(cond
((file-exists-p possible-file)
(throw 'found-it possible-file))
((string= "/SConstruct" possible-file)
(error "No SConstruct found"))
(t (find-sconstruct-r (directory-file-name parent)))))))
(if (buffer-file-name)
(catch 'found-it
(find-sconstruct-r (buffer-file-name)))
(error "Buffer is not visiting a file"))))
(defun project-root ()
(file-name-directory (find-sconstruct)))
You can then change your compile-command to use project-root e.g.
(concat "cd " (project-root) " && scons")
I use EDE (from CEDET) to define projects, and store compilation commands in the project definition. Look to my config for examples: lines 105-133 -- examples of projects, lines 135-165 -- code, that defines compilation functions, and lines 168-189 -- functions for different kinds of projects -- standard (compile from root directory), and cmake (compilation in separate directory)
Another alternative is to set the variable compilation-process-setup-function which is documented as:
Function to call to customize the compilation process. This function
is called immediately before the compilation process is started. It
can be used to set any variables or functions that are used while
processing the output of the compilation process. The function is
called with variables compilation-buffer' andcompilation-window'
bound to the compilation buffer and window, respectively.
I use Maven alot and wrote this library to support your issue for a Maven context. In the following, change the value of the variable compile-search-file as appropriate:
;;; Support for Maven 2
(require 'compile)
(setq compile-search-file "pom.xml")
(defun find-search-file ()
;; Search for the pom file traversing up the directory tree.
(setq dir (expand-file-name default-directory))
(let ((parent (file-name-directory (directory-file-name dir))))
(while (and (not (file-readable-p (concat dir compile-search-file)))
(not (string= parent dir)))
(setq dir parent
parent (file-name-directory (directory-file-name dir))))
(if (string= dir parent)
(error "Search file %s is missing" compile-search-file)
(with-current-buffer compilation-last-buffer
(message "Test %s %s." compilation-buffer compilation-window)
(setq default-directory dir)))))
;; Add the following to support Emacs' compile mode:
(add-to-list
'compilation-error-regexp-alist-alist
'(mvn "^\\(.*\\):\\[\\([0-9]*\\),\\([0-9]*\\)\\]" 1 2 3))
(add-to-list 'compilation-error-regexp-alist 'mvn)
(setq compilation-process-setup-function 'find-search-file)
(provide 'maven-support)
When I use Emacs to compile the minibuffer looks something like this;
make -k
and I just add any text I like, such as -f ../../root/Makefile. This might work for you.
Mark
I'm not much of an emacs user, but could you pass make -C ../ or however many directories up you need to go?
After a while of different attempts to make EDE work the way I wanted, I went for .dir-locals.el:
((c++-mode . ((compile-command . "make -C ../build -j2 whatever"))))
I found it slightly better for me than having a // -*- -*- in a header of every file,
and a whole lot better than specifying in my init.el (or any other config) those ede-cpp-root-project with full paths to projects, which I either create too often or move all of a sudden :)
Nice addition to the scheme was cmake which makes compile errors to be 'properly jumpable' since it uses full paths in generated makefiles.
I've just started working on a more generic, extensible, and robust yet still reasonably quick-and-dirty solution I just created. It's somewhat based on the Maven example above but I prefer not mucking around with global variables so I use the let or let* special forms a lot more. And of course it uses make.
Right now it only supports Makefiles but you can add a clause to the (cond) special form in the `my-compilation-process-setup-function' function if you want to support one or more additional different build systems.
It even has doc strings!
You'll see it at my Github eventually.
This should do it:
make -f path_to_rootdir/Makefile -I path_to_rootdir/tests
The -f tells it what makefile to use, the -I tells it where to look for files to be included in the makefile (that aren't in the local directory).
Start with M-x compile RET. When it prompts for a command, just enter cd /path/to/root && make and hit return. This command works for all variants of make and handles the "included makefile" problem without any extra flags.
The next time you type M-x compile RET, this new string will be presented as the default, so you only have to hit return. On the off chance that you're actively compiling multiple projects within emacs, you can use M-p and M-n to move backwards and forwards through the history of compile comamnds.