Emacs and company autocompletion. Add a header directory globally - emacs

I'm trying to add a header files path to company-mode but I can't do it. I did it with flycheck as follow:
(defun include-paths ()
(setq flycheck-clang-include-path (list (expand-file-name "../include"))))
(add-hook 'c++-mode-hook 'include-paths)
Is there a similar way to do it with company-mode?

I'm assuming you're using company-c-headers.
Almost verbatim from their README file, you can use M-x customize-groups, company-c-headers to modify the search directories.
Alternatively, you can bind the company-c-headers-path-system and company-c-headers-path-user variables to functions which return the corresponding paths. For example, if you are using EDE, you can use the following:
(defun ede-object-system-include-path ()
"Return the system include path for the current buffer."
(when ede-object
(ede-system-include-path ede-object)))
(setq company-c-headers-path-system 'ede-object-system-include-path)
Source

Related

emacs org-mode file local key binding

I'm using org-mode in emacs together with ox-reveal. The latter defines the command org-reveal-export-to-html, which I would like to bind to a key for buffers with org files, which are presentations (so not for all org files).
So the question is: how can I define file local key bindings in org-mode?
What I currently have is this:
#+BEGIN_COMMENT
Local Variables:
eval: (local-set-key [f5] 'org-reveal-export-to-html)
End:
#+END_COMMENT
But imho this is not very elegant.
You can define a key only for org-mode by using org-defkey, basically add the following to your init file
(org-defkey org-mode-map [f5] 'org-reveal-export-to-html)
UPDATE
You can use file local variables.
(defvar export-with-reveal nil)
(defun export-with-reveal-or-html ()
(interactive)
(if (or export-with-reveal (file-exists-p "reveal.js"))
(call-interactively 'org-reveal-export-to-html)
(call-interactively 'org-export-as-html)))
(org-defkey org-mode-map [f5] 'export-with-reveal-or-html)
The function export-with-reveal-or-html if the variable export-with-reveal has value t or there is a file 'reveal.js' relative to org file , if so it exports with reveal or it falls back to default html export. You can specify a file to exported as reveal by adding the following to top of your org file
# -*- export-with-reveal: t -*-
UPDATE 2
You can also define arbitrary export function by doing using, file-local variables
(defvar my-export-fn nil)
(defun my-export ()
(interactive)
(if my-export-fn
(call-interactively my-export-fn)
(call-interactively 'org-export-as-html)))
(org-defkey org-mode-map [f5] 'my-export)
Then at top of the file you can set the export function you want to use eg
# -*- export-fn: org-reveal-export-to-html -*-
I came up with following solution, which exploits local variables hook hack and defines buffer lokal hook:
(add-hook 'org-mode-hook 'my-org-mode-hook)
(defun my-org-mode-hook ()
(add-hook 'hack-local-variables-hook
(lambda ()
(local-set-key [f5] (if (boundp 'my-org-export)
my-org-export
'org-html-export-to-html)))))
Then in org mode I add this:
#+BEGIN_COMMENT
Local Variables:
my-org-export: org-reveal-export-to-html
End:
#+END_COMMENT
Still I would love to see something like this, without any hook hacking:
#+EXPORT: org-reveal-export-to-html

How do I get the path from which init.el was loaded?

I am looking to create a custom config for emacs to use for Erlang work and I want to refer to my custom EDTS repo as being under the directory from which init.el was loaded. Right now I have this:
(add-to-list 'load-path "~/.emacs-edts/edts/")
But I would rather not hardcode it and refer to it by variable.
Suggestions?
Strictly speaking the answer is (file-name-directory user-init-file), but instead see C-hv user-emacs-directory
I have the following snippet in my init.el:
(setq my-init-dir
(file-name-directory
(or load-file-name (buffer-file-name))))
This has the advantage of working whether init.el is in your emacs.d directory or not.
I have the following in my init file:
(defun my-file-name-basename (s)
"The directory name, without the final part.
For example:
(my-file-name-basename \"alpha/beta/gamma\") => \"alpha/beta\""
(substring (file-name-directory s) 0 -1))
;; Note: Normally, it's not possible to find out the file a specific
;; function is defined in. However, it's possible to save the file
;; name at the time this file was loaded.
(defvar my-load-file-name load-file-name
"The file name of this file.")
(defun my-start-directory (&optional path)
"The root directory that contains this module.
When PATH is specified, return the start directory concatenated with PATH.
Otherwise return the directory with a trailing slash."
;; Note: Try to figure out where we are, so that we can add the
;; subdirectories. `load-file-name' only works when the file is
;; loaded. Picking up the file from the symbol works when this is
;; evaluated later.
(let ((file-name (or my-load-file-name
(symbol-file 'my-start-directory)
;; Default value. (This is used, for example,
;; when using `eval-buffer' or `eval-region'.)
"~/emacs")))
(let ((start (concat (my-file-name-basename
(my-file-name-basename file-name))
"/")))
(if path
(concat start path)
start))))
In addition to finding out where the file containing the above above code is located (which does not have to be the init file), it provides a convenient way to create paths based on it. For example:
(setq custom-file (my-start-directory "init/custom.el"))

How to make all org-files under a folder added in agenda-list automatically?

I am using org-mode to write notes and org-agenda to organize all notes, especially to search some info. by keyword or tag.
C-c a m can search some files by tag inputed, C-c a s by keyword ,those functions from org-agenda are well to utilize, however, I need to add org-file into the agenda-list by hand.
I added some codes into .emacs, such as
(setq org-agenda-files (list "path/folder/*.org"))
or
(setq org-agenda-files (file-expand-wildcards "path/folder/*.org"))
but, both failed to add files under the folder specified into agenda-list automatically, so I can't search keyword or tag among those org-files, unless that I open a org-file and type C-c [ to add it into agenda-list.
How can I make all org-files under a folder automatically added in agenda?
Just naming the directory should be enough. For example this works for me very well:
(setq org-agenda-files '("~/org"))
Also take a look at org-agenda-text-search-extra-files; it lets you
add extra files included only in text searches. A typical value might
be,
(setq org-agenda-text-search-extra-files
'(agenda-archives
"~/org/subdir/textfile1.txt"
"~/org/subdir/textfile1.txt"))
Caveat: If you add a file to the directory after you have started
Emacs, it will not be included.
Edit: (2018) To include all files with a certain extension in the extra files list you can try the following function I wrote sometime back (a more recent version might be available here).
;; recursively find .org files in provided directory
;; modified from an Emacs Lisp Intro example
(defun sa-find-org-file-recursively (&optional directory filext)
"Return .org and .org_archive files recursively from DIRECTORY.
If FILEXT is provided, return files with extension FILEXT instead."
(interactive "DDirectory: ")
(let* (org-file-list
(case-fold-search t) ; filesystems are case sensitive
(file-name-regex "^[^.#].*") ; exclude dot, autosave, and backupfiles
(filext (or filext "org$\\\|org_archive"))
(fileregex (format "%s\\.\\(%s$\\)" file-name-regex filext))
(cur-dir-list (directory-files directory t file-name-regex)))
;; loop over directory listing
(dolist (file-or-dir cur-dir-list org-file-list) ; returns org-file-list
(cond
((file-regular-p file-or-dir) ; regular files
(if (string-match fileregex file-or-dir) ; org files
(add-to-list 'org-file-list file-or-dir)))
((file-directory-p file-or-dir)
(dolist (org-file (sa-find-org-file-recursively file-or-dir filext)
org-file-list) ; add files found to result
(add-to-list 'org-file-list org-file)))))))
You can use it like this:
(setq org-agenda-text-search-extra-files
(append (sa-find-org-file-recursively "~/org/dir1/" "txt")
(sa-find-org-file-recursively "~/org/dir2/" "tex")))
Edit: (2019) As mentioned in the answer by #mingwei-zhang and the comment by #xiaobing, find-lisp-find-files from find-lisp and directory-files-recursively also provides this functionality. However, please note in these cases the file name argument is a (greedy) regex. So something like (directory-files-recursively "~/my-dir" "org") will give you all Org files including backup files (*.org~). To include only *.org files, you may use (directory-files-recursively "~/my-dir" "org$").
There is a simpler way of doing recursive search of org files (courtesy #xiaobing):
(setq org-agenda-files (directory-files-recursively "~/org/" "\\.org$"))
EDIT: You can also filter out certain directory from lookup by adding a array filter. Example, filtering out all org files in xxxx/xxx/daily/ directory:
(setq org-agenda-files
(seq-filter (lambda(x) (not (string-match "/daily/"(file-name-directory x))))
(directory-files-recursively "~/Notes/roam" "\\.org$")
))
For Emacs <25, you can use find-lisp-find-files:
(load-library "find-lisp")
(setq org-agenda-files
(find-lisp-find-files "FOLDERNAME" "\.org$"))

emacs: open all .txt files in a specific directory in a specific major mode

EDIT: It turns out that the second edit to my .emacs file actually works. (See the comments below this entry.)
I tried a couple of addition to the .emacs to make all txt files opened in emacs use orgmode. They did not work. How can I make it happen?
;;SET EMACS AS DEFAULT MAJOR MODE TO FOR ALL FILES WITH AN UNSPECIFIED MODE
(setq default-major-mode 'org-mode)
;;OPEN ALL TXT FILES IN ORGMODE
(add-to-list 'auto-mode-alist '("\\.txt$" . org-mode))
Additionally:
It would be even better to open only txt files in a certain directory orgmode. Any hint as to how that could be done would also be appreciated.
Another way to do this is using directory-local variables. This is nice because you can put a file in any directory where you want this behavior to engage, and it works recursively in any subdirectories.
Create a file called .dir-locals.el in the desired directory.
Here are the contents:
((nil (eval . (if (string-match ".txt$" (buffer-file-name))(org-mode)))))
Read this like so: for any major-mode (nil), evaluate the following form:
(if .... (org-mode))
The regex in auto-mode-alist could be something more complex, like "^/path/to/.*\\.txt$"
You can implement a hook which verifies the file directory and modifies the buffer mode:
(add-hook 'find-file-hooks
(lambda ()
(let ((file (buffer-file-name)))
(when (and file (equal (file-name-directory file) "c:/temp/"))
(org-mode)))))
As an alternative you can add the mode line in the beginning of your text file. In this case emacs will set the specified mode.
; -*- mode: org;-*-
* header 1
** header 2
I glued together some code from Oleg Pavliv's answer here, and from yibe's at elisp - File extension hook in Emacs - Stack Overflow
(defun use-org-mode-for-dot-txt-files-in-owncloud ()
(when (and (string-match owncloud buffer-file-name)
(string-match "\\.txt\\'" buffer-file-name))
(org-mode)))
(add-hook 'find-file-hook 'use-org-mode-for-dot-txt-files-in-owncloud)
This way, though ownCloud Web and phone apps are currently friendly only with .txt files, from my PC I can use Emacs' Org-mode for them.
(If I set all .txt files to use Org-mode, it breaks todotxt-mode.)
(Note that owncloud is a string variable equal to my ownCloud path.)

How to run hook depending on file location

I am involved in python project where tabs are used, however i am not using them in every other code i write, it is vital to use them in that particular project. Projects are located in one directory under specific directories. I.E:
\main_folder
\project1
\project2
\project3
...etc
I have couple functions/hooks on file open and save that untabify and tabify whole buffer i work on.
;; My Functions
(defun untabify-buffer ()
"Untabify current buffer"
(interactive)
(untabify (point-min) (point-max)))
(defun tabify-buffer ()
"Tabify current buffer"
(interactive)
(tabify (point-min) (point-max)))
;; HOOKS
; untabify buffer on open
(add-hook 'find-file-hook 'untabify-buffer)
; tabify on save
(add-hook 'before-save-hook 'tabify-buffer)
If i put it in .emacs file it is run on every .py file i open which is not what i want. What i`d like to have is to have these hooks used only in one particular folder with respective subfolders. Tried .dir_locals but it works only for properties not hooks. I can not use hooks in specific modes (i.e. python-mode) as almost all projects are written in python. To be honest i tried writing elisp conditional save but failed.
A very easy solution is to just add a configuration variable that can be used to disable the hooks. For example:
(defvar tweak-tabs t)
(add-hook 'find-file-hook
(lambda () (when tweak-tabs (untabify (point-min) (point-max)))))
(add-hook 'before-save-hook
(lambda () (when tweak-tabs (tabify (point-min) (point-max)))))
Now you can add a .dir-locals.el file in the relevant directories, setting tweak-tabs to nil, disabling this feature there.
(But another problem is that this is a pretty bad way to deal with tabs. For example, after you save a file you do see the tabs in it.)
Just for the record, to answer the literal question in the title (as I reached this question via a web search): one way to add a hook that depends on file location is to make it a function that checks for buffer-file-name. (Idea from this answer.)
For example, for the exact same problem (turn on tabs only in a particular directory, and leave tabs turned off elsewhere), I'm currently doing something like (after having installed the package smart-tabs-mode with M-x package-install):
(smart-tabs-insinuate 'python) ; This screws up all Python files (inserts tabs)
(add-hook 'python-mode-hook ; So we need to un-screw most of them
(lambda ()
(unless (and (stringp buffer-file-name)
(string-match "specialproject" buffer-file-name))
(setq smart-tabs-mode nil)))
t) ; Add this hook to end of the list
(This is a bit inverted, as smart-tabs-insinuate itself modifies python-mode-hook and then we're modifying it back, but it should do as an example.)