Cedet is a nice tool suite but in default configuration it has some difficulty locating included files.
I would like to make it look for a directory called include/ in each parent directory and get the file from there.
for examplme a file /home/fakedrake/my-project/some-thing/something-else/file.c has #include "file.h"
file.h is in some-thing/file.h but cedet fails to locate it
What would be awesome would be to make cedet look for file.h to create completions in directories
/home/fakedrake/my-project/some-thing/include/
/home/fakedrake/my-project/include/
( and i could live with it if it tried to look for
/include/
/home/include/
/home/fakedrake/include/
)
You can use EDE for it. Moreover, it allows you to specify different include paths for particular projects. EDE is a part of Cedet, so you needn't install anything.
The basic setup is:
(global-ede-mode t)
Then for each project you should have something like that:
(if (file-exists-p "~/dev/chanconf/Makefile")
(ede-cpp-root-project "chanconf"
:name "Channel Config"
:file "~/dev/chanconf/Makefile"
:system-include-path '("/usr/include"
"/usr/include/boost")
:include-path '("/src"
"/test/gtest/include")
:spp-table '(("BOOST_PROGRAM_OPTIONS_DECL" . ""))))
It's not exactly what you're asking for since you still have to list all the include directories. But usually it's done only one time per project and doesn't require too much effort, so I hope it helps.
An article on Cedet by Alex Ott is a pretty good source of ideas if you need more.
Related
In latest version of ̀emacs ( from 24.3.50 snapshot) there is a warning at startup when .emacs.d happens to be in the load path.
Warning (initialization): Your `load-path' seems to contain
your `.emacs.d' directory: ~/.emacs.d/
This is likely to cause problems...
Consider using a subdirectory instead, e.g.: /home/adriean/.emacs.d/lisp
Is there a way to disable just this warning?
(since I wanna keep my emacs.d in the load path, for now as a quick brute hack I went for (setq warning-minimum-level :error), but I would prefer to get rid of this as soon as possible)
Don't disable the warning. It's there for a good reason: ~/.emacs.d shouldn't be in your load-path.
This is because Emacs writes files to this directory, and therefore it's possible (there are existing cases) for those files to conflict with the names of elisp libraries. If you have this directory in your load path, and you have such a name clash, then Emacs will attempt to load the wrong file if that library is required.
Just change your configuration. It's trivial to move the elisp libraries you've placed in that directory into a sub-directory, and then update the code which was adding ~/.emacs.d to your load-path, so that it adds the new sub-directory instead:
(add-to-list 'load-path (expand-file-name "~/.emacs.d/lisp"))
Precaution
Your .emacs.d can safely be in your load-path only at the end. This will ensure that if a file in your .emacs.d conflicts with a library, the library will take precedence. With add-to-list, you can do this by setting the third parameter (APPEND) to t:
(add-to-list 'load-path (expand-file-name "~/.emacs.d") t)
Disabling the warning
Adding 'initialization to warning-suppress-types or warning-suppress-log-types will suppress the warning, but you also won't see errors or warnings if something goes wrong in your init file.
The solution I use in my .emacs.d is an advice that selectively ignores this warning based on the warning message:
(defadvice display-warning
(around no-warn-.emacs.d-in-load-path (type message &rest unused) activate)
"Ignore the warning about the `.emacs.d' directory being in `load-path'."
(unless (and (eq type 'initialization)
(string-prefix-p "Your `load-path' seems to contain\nyour `.emacs.d' directory"
message t))
ad-do-it))
This will need updating if the warning message changes.
Organization tip
If you want to keep personal files directly in your .emacs.d directory, it may be a good idea to unclutter it by making a dedicated directory for the savefiles of various packages, for example:
(defvar my-savefile-dir (expand-file-name "savefiles" "~/.emacs.d")
"The directory for automatically generated save/history/etc. files.")
and then, for each package that puts its file in .emacs.d, something like this:
(setq tramp-persistency-file-name
(expand-file-name "tramp" my-savefile-dir))
Update to organization tip
Since writing the above, I've discovered that packages usually use locate-user-emacs-file to get the paths to files in which they store their data. This function returns an absolute path to a file in user-emacs-directory. By default, user-emacs-directory contains the path to your .emacs.d, but you can change this to a directory where you want your savefiles (you'll probably also want to preserve the old value somewhere):
(defvar main-dir user-emacs-directory
"The root directory of my Emacs configuration.")
(setq user-emacs-directory (expand-file-name "savefiles/" main-dir))
;; The trailing slash is mandatory.
This will make most packages store their files in .emacs.d/savefiles. If you want to make an exception, so that a given package stores its files directly in .emacs.d, use something like this:
(setq package-user-dir (expand-file-name "elpa" main-dir))
You'll also have to change settings of packages that get loaded before your init file, and therefore use the original value of user-emacs-directory:
(setq auto-save-list-file-prefix
(locate-user-emacs-file "auto-save-list/.saves-"))
In addition, some packages use hardcoded paths instead of locate-user-emacs-file, but that's easy to fix too:
(setq smex-save-file (locate-user-emacs-file "smex"))
Most packages use locate-user-emacs-file though, so in my experience this method of organizing savefiles requires less code than the one from the original "organization tip" (as of writing this, the above fragments of code are the only savefile settings in my Emacs configuration, while the original method required a line for each package).
I don't know if this method is an intended use or an abuse of the user-emacs-directory variable. I use it and it works without issues so far, but your mileage may vary.
You could add initialization to either warning-suppress-log-types (don't log the warning at all), or warning-suppress-types (log the warning, but don't pop up the warnings buffer).
I had the same issue recently, on 4.4.0-22-generic GNU/Linux (Ubuntu 16.04 LTS) and for me the only thing that worked is:
$ chown -R my_user ~/.emacs.d
$ # Fix the 'broken' permissions
You might get chown: cannot read directory '/home/my_user/.emacs.d': Permission denied then simply do:
sudo chown -R my_user:my_group ~/.emacs.d
It worked like a charm for me.
Ref. The source of the answer was taken from Permission issue with emacs for non-root user (Ubuntu 11.10).
It seems like Project.ede only accepts predefined project, which are Arduino Sketch, Android, Automake and Make. I pasted ede-cpp-root-project, but upon entering project root that has Project.ede, I encountered this error:
eieio-persistent-read: Corrupt object on disk: Unknown saved object
Here is the ede-cpp-root-project I pasted into:
(ede-cpp-root-project "Coloring"
:file "~/workspace/discrete_optimization/hw2/Project.ede"
:include-path '("/"
"/include"
"/include2"
"/include3"))
I really want to create a file per project, not in a centralized file.
Use of a Project.ede file is only for a specific project type of Make or Automake. While you could type it in by hand, you should use ede-new for creating them. Also, only use that type of project if you want EDE to create your Makefiles for you. You are getting the the 'corrupt' message because Emacs will refuse to load the file if it finds anything other than one of the two support project types.
If you would like to use ede-cpp-root-project, you can create any old file like "myproject.el" and put your ede-cpp-root-project config in it. Then do
M-x load-file RET /path/to/myproject.el
to load it up when needed.
I recently switched to the use of emacs' package manager packages.
Since then, some emacs path variables get set beyond what I do in my .emacs file: Both load-path and Info-directory-list get perpended with stuff from the packages. But I don't understand where these customisations are done.
Let's concentrate on Info-directory-list: In my .emacs file I don't set it so it should be nil (so that later when info starts up, its initialised from Info-default-directory-list. However with my new packaging it is already intialised and some package directories are added. This messes up my dir structure in info. I have checked the autoload files, but they don't set Info-directory-list in any way - and no other elisp file in the packages (pandoc-mode in particular) do so.
Where is the Info-directory-list variable set and how can I regain control over the order in this variable?
After evaluating your init file, Emacs calls package-initialize (which does what it sounds like). After initializing the packages, Emacs runs after-init-hook, so if you want to manipulate variables which have been modified during package initialisation, you can put the following in your init file:
(add-hook 'after-init-hook 'my-after-init-hook)
(defun my-after-init-hook ()
"After package initialisation."
;; do something with Info-directory-list
)
You can also call package-initialize yourself, provided that you ensure that any necessary package-related variables are set beforehand. See Emacs 24 Package System Initialization Problems for details.
As for how and why Info-directory-list is being modified, the manual comments on that aspect in (elisp) Multi-file Packages:
A multi-file package is less convenient to create than a single-file
package, but it offers more features: it can include multiple Emacs
Lisp files, an Info manual, and other file types (such as images).
[...]
If the content directory contains a file named dir, this is
assumed to be an Info directory file made with install-info. *Note
Invoking install-info: (texinfo)Invoking install-info. The relevant
Info files should also be present in the content directory. In this
case, Emacs will automatically add the content directory to
Info-directory-list when the package is activated.
Specifically, package-activate-1 does this:
(when (file-exists-p (expand-file-name "dir" pkg-dir))
;; FIXME: not the friendliest, but simple.
(require 'info)
(info-initialize)
(push pkg-dir Info-directory-list))
I'm using CMake 2.8.2 version. The project is using lots of external files and custom libraries (unavailable through find_package) and there is a long cascade of elements like the one below:
find_path(XXX_INCLUDE_DIR XXX.h /XXX/include)
if (XXX_INCLUDE_DIR)
message(STATUS "Includes (XXX) found in ${XXX_INCLUDE_DIR}")
else()
message(FATAL_ERROR "Includes (XXX) not found")
endif()
There is over 20 things like this in the script - it doesn't look good. According to the documentation, unfortunately, neither find_path nor find_library have a REQUIRED option which would do the job here (just like it does with find_package - if not found, the script stops). Do you have an idea how can I shorten the CMake script code? Something like
find_path(XXX_INCLUDE_DIR XXX.h /XXX/include REQUIED)
or something similar would be great.
Put them in your custom FindXXX.cmake modules. Read the docs and look at FindPNG.cmake for an example. Put them into <project>/cmake/FindXXX.cmake (or similar), and then add the directory containing these files to the CMAKE_MODULE_PATH and use find_package(), e.g.
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
find_package(XXX REQUIRED)
You probably want to use either a macro or a function.
Rather than individually specifing each subdirectory in my plugins directory I want to be able to automatically load them, to that end I included the following to my .emacs file:
(let ((base "~/.emacs.d/plugins/"))
(normal-top-level-add-subdirs-to-load-path))
require 'rinari
require 'yasnippet
Unfortunately the above results in: File error: Cannot open load file, rinari
Anyone know what's wrong and how to fix it?
You're so close...
(let ((default-directory "~/.emacs.d/plugins/"))
(normal-top-level-add-subdirs-to-load-path))
normal-top-level-add-subdirs-to-load-path works off the current directory, which you can set via the variable default-directory - not base like you tried.
You might investigate the role of the subdirs.el files during startup. It is a good way get subdirectories into your load-path.
For example, much of the default load-path arises as a consequence of the files discovered by this command:
find /usr -name subdirs.el