Adding a custom yasnippet directory to `Spacemacs` - emacs

Sorry for the very newb question, but was just trying to configure a separate directory for yasnippets in spacemacs. I am not familar with emacs lisp at all. So it says that I can put the directory in
(setq-default dotspacemacs-configuration-layers '(
(auto-completion :variables
auto-completion-return-key-behavior 'complete
auto-completion-tab-key-behavior 'cycle
auto-completion-complete-with-key-sequence nil
auto-completion-complete-with-key-sequence-delay 0.1
auto-completion-private-snippets-directory nil)
))
so I have to set the auto-completion-private-snippets-directory, but I was not sure how to configure a custom directory like "~/Dropbox/snippets". I tried the code below with the added directory, but it was not working.
dotspacemacs-configuration-layers '(
...
auto-completion-private-snippets-directory "~/Dropbox/snippets")
))
I was not sure if I need to try pushing the new directory to the variable, etc. Any suggestions.

I figured out how to do this. Basically just needed to append directories to the yas-snippet-dirs variable. These additional directories are then added to the list of directories from which yasnippet gathers snippets.
;; Snippet configuration
(setq-default dotspacemacs-configuration-layers '(
(auto-completion :variables
auto-completion-return-key-behavior 'complete
auto-completion-tab-key-behavior 'cycle
auto-completion-complete-with-key-sequence nil
auto-completion-complete-with-key-sequence-delay 0.1
auto-completion-enable-snippets-in-popup t
auto-completion-enable-sort-by-usage t
auto-completion-enable-help-tooltip t
auto-completion-private-snippets-directory nil)
))
;; add extra snippet directories
(setq yas-snippet-dirs (append yas-snippet-dirs
'("/home/<username>/Dropbox/.../snippets")))
(setq yas-snippet-dirs (append yas-snippet-dirs
'("/home/<username>/Dropbox/.../more_snippets")))

Related

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

Recursively adding .org files in a top-level directory for org-agenda-files takes a long time

I'm trying to find a way to quickly recurse through every subdirectory searching for org files. I've found several solutions (Elisp Cookbook, and several solutions on github), but they don't handle my real world usage (hundreds of directories (and subdirectories) and hundreds of org files). They seem to run forever on my system (Windows 7, with max-lisp-eval-depth = 10000). My work around is to add each directory manually to my org-agenda-list, but it's annoying and I know I've probably forgotten some. Any suggestions would be appreciated.
Haven't seen other people post this, so I will do.
Have you tried load "find-list" library and use its "find-lisp-find-files" function?
I added these lines in my org config and it works, but it may not fit your performance requirement:
(load-library "find-lisp")
(setq org-agenda-files
(find-lisp-find-files "FOLDERNAME" "\.org$"))
source: http://emacs-orgmode.gnu.narkive.com/n5bQRs5t/o-multiple-recursive-directories-with-org-agenda-files
The following code works well in emacs 24.3+:
;; Collect all .org from my Org directory and subdirs
(setq org-agenda-file-regexp "\\`[^.].*\\.org\\'") ; default value
(defun load-org-agenda-files-recursively (dir) "Find all directories in DIR."
(unless (file-directory-p dir) (error "Not a directory `%s'" dir))
(unless (equal (directory-files dir nil org-agenda-file-regexp t) nil)
(add-to-list 'org-agenda-files dir)
)
(dolist (file (directory-files dir nil nil t))
(unless (member file '("." ".."))
(let ((file (concat dir file "/")))
(when (file-directory-p file)
(load-org-agenda-files-recursively file)
)
)
)
)
)
(load-org-agenda-files-recursively "/path/to/your/org/dir/" ) ; trailing slash required
It does not require intermediate files creation and you can put it on a shortcut as well.
To be able to refile to any file found add this:
(setq org-refile-targets
'((nil :maxlevel . 3)
(org-agenda-files :maxlevel . 1)))
How about storing the list of org-agenda directories in a file that you (automatically) update every once in a while, when you know the direcory structure has changed and you have some time.
You could for example use something like this:
;; From http://www.emacswiki.org/emacs/ElispCookbook#toc58
(defun directory-dirs (dir)
"Find all directories in DIR."
(unless (file-directory-p dir)
(error "Not a directory `%s'" dir))
(let ((dir (directory-file-name dir))
(dirs '())
(files (directory-files dir nil nil t)))
(dolist (file files)
(unless (member file '("." ".."))
(let ((file (concat dir "/" file)))
(when (file-directory-p file)
(setq dirs (append (cons file
(directory-dirs file))
dirs))))))
dirs))
(setq my-org-agenda-root "~/org")
(setq my-org-agenda-files-list "~/.emacs.d/org-agenda-list.el")
(defun my-update-org-agenda-files ()
"Create or update the `my-org-agenda-files-list' file.
This file contains elisp code to set `org-agenda-files' to a
recursive list of all children under `my-org-agenda-root'. "
(interactive)
(with-temp-buffer
(insert
";; Warning: this file has been automatically generated\n"
";; by `my-update-org-agenda-files'\n")
(let ((dir-list (directory-dirs my-org-agenda-root))
(print-level nil)
(print-length nil))
(cl-prettyprint `(setq org-agenda-files (quote ,dir-list))))
(write-file my-org-agenda-files-list)))
(load my-org-agenda-files-list)
Every once in a while, run M-xmy-update-org-agenda-files to update the list.
As of Emacs 25, you can use directory-files-recursively which returns all files matching a regex from a root directory.
(defun org-get-agenda-files-recursively (dir)
"Get org agenda files from root DIR."
(directory-files-recursively dir "\.org$"))
(defun org-set-agenda-files-recursively (dir)
"Set org-agenda files from root DIR."
(setq org-agenda-files
(org-get-agenda-files-recursively dir)))
(defun org-add-agenda-files-recursively (dir)
"Add org-agenda files from root DIR."
(nconc org-agenda-files
(org-get-agenda-files-recursively dir)))
(setq org-agenda-files nil) ; zero out for testing
(org-set-agenda-files-recursively "~/Github") ; test set
(org-add-agenda-files-recursively "~/Dropbox") ; test add
You can view the contents of org-agenda-files by typing C-hv org-agenda-files.
Little late to the party, and probably not the answer you were hoping for, but the only way I found to speed up my agenda load times was by not including some directories which had thousands of org files.
(setq org-directory "~/org/"
my-agenda-dirs '("personal" "projects" "todos" "work")
org-agenda-files (mapcan (lambda (x) (directory-files-recursively
(expand-file-name x org-directory)
"\.org$"))
my-agenda-dirs))
Essentially rather than recursing over my entire org dir I only recurse through a select few of it's subdirs.
I also tried "recursive directory listing" at Emacs startup. It simply is way to loooong to be usable. So, try to stick with a limited number of "root" directories where you put your agenda files.
Even better is sticking with "~/org", and possibly a few subdirs like "work" and "personal", and that's it. You can put there your agenda files, and have links Inside them to your real project root dirs.
I know, this is not optimal, but I don't have anything better right now.

Emacs: load only necessary yasnippets

Suppose, I have 2 subdirectories for yasnippets:
~/.emacs.d/yasnippets/perl-mode
~/.emacs.d/yasnippets/php-mode
Currently I use the following code in my .emacs:
(defvar *my-emacs-lib-dir* "~/.emacs.d/")
(load (concat *my-emacs-lib-dir* "plugins/yasnippet/yasnippet"))
(setq yas/snippet-dirs nil)
(yas/initialize)
;; Develop and keep personal snippets under ~/emacs.d/yasnippets
(setq yas/root-directory (concat *my-emacs-lib-dir* "yasnippets"))
(yas/load-directory yas/root-directory)
So, it loads all the yasnippets in all the subdirectories of ~/.emacs.d/yasnippets.
Is it possible to make it load the yasnippets on demand? If I open a php file, and the snippets for php-mode were not loaded, load them. But not load everything on startup.
If I remember correctly, in fresh versions, the loading of snippets will performed on demand, if you'll use recommended loading sequence:
(add-to-list 'load-path "~/path-to-yasnippet")
(require 'yasnippet)
(yas-global-mode 1)
You can also use the optional use-jit flag to the yas-load-directory function, that will force on demand loading of snippets from this directory. See description of this function (C-h f yas-load-directory)
Maybe something like this can work.
(defvar yas/loaded-php-snippets nil)
(defun yas/load-php-snippets()
(if (not yas/loaded-php-snippets)
(progn
(yas/load-directory (concat yas/root-directory) "/php-mode")
(setq yas/loaded-php-snippets t))))
(add-hook 'php-mode-hook 'yas/loaded-php-snippets)
This is just an example but one could conceivably have map between mode-hooks and yas load directories and just load specific directories if they are not yet been loaded.

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$"))

How can I hide the backup files that emacs creates?

I just started using emacs after having used vi for a long time. :)
One thing which is annoying me is that whenever I modify a file, save it and exit emacs, I see a backup file created in the same directory named filename~ (if the file I edited was filename).
Is there any way I can get rid of this? Or hide these files? It is very annoying to see tons of backup files when I do ls of the directory.
You can either move them to their own folder with the following code:
;; Don't clutter up directories with files~
(setq backup-directory-alist `(("." . ,(expand-file-name
(concat dotfiles-dir "backups")))))
;; Don't clutter with #files either
(setq auto-save-file-name-transforms
`((".*" ,(expand-file-name (concat dotfiles-dir "backups")))))
Or you can remove them completely, like so:
(setq make-backup-files nil)
(setq auto-save-default nil)
Personally I would be wary of removing them as they can come in useful. Further discussion is here:
http://www.emacswiki.org/emacs/BackupDirectory
http://www.emacswiki.org/emacs/AutoSave
I would recommend checking out the emacs-starter-kit it sorts out a load of issues that people have when coming to emacs, and is pretty heavily used.
http://github.com/technomancy/emacs-starter-kit/blob/master/starter-kit-misc.el
Update:
There seems to be much confusion over how to use the functions. I'm going to have a little play around later but here is some more information. Note that auto-save-file-name-transforms:
lets you specify a series of regular expressions and replacements to transform the auto save file name
[emacs-manual]
so it's not just as simple as adding in a folder name. That said it seems from a quick google search the following might just do what you all want:
;;; backup/autosave
(defvar backup-dir (expand-file-name "~/.emacs.d/backup/"))
(defvar autosave-dir (expand-file-name "~/.emacs.d/autosave/"))
(setq backup-directory-alist (list (cons ".*" backup-dir)))
(setq auto-save-list-file-prefix autosave-dir)
(setq auto-save-file-name-transforms `((".*" ,autosave-dir t)))
http://www.google.com/codesearch?hl=en&lr=&q=auto-save-file-name-transforms&sbtn=Search
The following lines in ~/.emacs will put all of the auto-save and backup files in /tmp:
(setq backup-directory-alist
`((".*" . ,temporary-file-directory)))
(setq auto-save-file-name-transforms
`((".*" ,temporary-file-directory t)))
In your .emacs:
(setq make-backup-files nil)
Edit:
If you're unfamiliar with the .emacs file, it's a file named .emacs that resides in your user $HOME directory. If you don't have one already, you can just create it and emacs will load it on startup.
Here is a link to the same question answered on SuperUser and my response. And a StackOverflow question entitled Emacs: Don’t create #these# files when not saving modified buffer
And for completeness, as stated by others; to stop the backup files being created put this in your .emacs
(setq make-backup-files nil)