I have a number of utility functions in a file called my-utils.el
. The first one I wrote was add-path
.
add-path
(defun add-path (&rest path) (let ((full-path "")) (dolist (var path) (setq full-path (concat full-path var))) (add-to-list 'load-path (expand-file-name full-path))))
This means that when I add a new third-party library (in its own directory), I can just write:
(add-path *elisp-dir* "muse-3.12")
I have a function called identity
that returns whatever was passed to it.
(defun identity (e) e)
This is particularly useful in functions like mapconcat
.
(defun add-path (&rest path) (add-to-list 'load-path (mapconcat #'identity path "")))
I like this function that I found on the internet a while ago (can’t find it again for attribution unfortunately).
insert-YYMMDD
(defun insert-YYYMMDD () (interactive) (insert (format-time-string "%Y%m%d")))
remove-dupes
remove-dupes
removes duplicate items that are next to each other in a list in the same way that uniq
does. (I mentioned this previously in one of the enabling your users posts.)
(defun remove-dupes (list) (let (tmp-list head) (while list (setq head (pop list)) (unless (equal head (car list)) (push head tmp-list))) (reverse tmp-list)))
assoc-replace
Sometimes you will have an assocation list where you just want to replace one of the values.
(defun assoc-replace (seq values) "Replace an element within an association list where the cars match." (mapcar (lambda (elem) (let* ((key (car elem)) (val (assoc key values))) (if val (cadr val) elem))) seq))
And often, only the cdr needs to change so kv
is a shortcut for that case. (kv 'a 'b)
returns (a (a . b))
.
(defsubst kv (k v) `(,k (,k . ,v)))
(These functions were mentioned in emacs association lists)
ext-mode-map
ext-mode-map
allows me to easily setup a major mode for extensions that are inconsistently capitalized.
(defun file-extensions (l) (concat "\\.\\(" (mapconcat (lambda (s) (mapconcat (lambda (c) (let ((c (upcase (char-to-string c)))) (concat "[" c (downcase c) "]"))) (symbol-name s) "")) l "\\|") "\\)\\'")) (defun ext-mode-map (extensions mode) (cons (file-extensions extensions) mode))
Then, for example, I can setup my perl extensions like this:
(add-to-list 'auto-mode-alist (ext-mode-map '(pl perl pm) 'cperl-mode))
(These functions were previously mentioned in autoloading an emacs major mode)
duplicate-current-line
I’m still using this function to duplicate the current line. It works unless you are on the final line which is very rare and you can work around that by opening a line below.
(defun duplicate-current-line () (interactive) (beginning-of-line nil) (let ((b (point))) (end-of-line nil) (copy-region-as-kill b (point))) (beginning-of-line 2) (open-line 1) (yank) (back-to-indentation))
(This function was mentioned previously in A Simple Emacs Shortcut – Duplicate Line)
set-longlines-mode
I often copy text into buffer and want to read it nicely wrapped around. I’ll change this function to use visual-line-mode
when all my emacs versions are upgraded to 23.
(defun set-longlines-mode () (interactive) (text-mode) (longlines-mode 1))
count-words
Other people have talked about their own count-words
functions in the past. I have my own ideas about what constitutes a word.
(defun count-words () (interactive) (let ((words (count-matches "[-A-Za-z0-9][-A-Za-z0-9.]*" (point-min) (point-max)))) (message (format "There are %d words" words))))
regex-replace and string-repeat
I sometimes have a text transform that I want to apply globally to a buffer. Exercise for the reader, fix regex-replace
to only apply to a region if one is selected.
(defun regex-replace (regex string) (goto-char (point-min)) (while (re-search-forward regex nil t) (replace-match string))) (defun string-repeat (str n) (let ((retval "")) (dotimes (i n) (setq retval (concat retval str))) retval))
I don’t know why you’d want `identity’, since it’s a C builtin:
`identity is a built-in function in `C source code’.
(identity arg)
Return the argument unchanged.’
You might also look at `normal-top-level-add-subdirs-to-load-path’, which adds all subdirectories of a path to load-path. You can just point it at your lisp folder and you don’t have to worry about maintaining the load-path anymore.
ELisp also has `delete-dups’, and there’s `delete-duplicates’ in cl.el. Both alter the source list. There’s `remove-duplicates’ (also in cl.el), which returns a copy with dupes removed. And more generally, there’s `remove-if’.
Here’s my duplicate-line, which will DTRT, at least for me:
(defun duplicate-line (&optional arg)
“Duplicate the current line to the line below”
(interactive “p”)
(let ((beg (line-beginning-position))
(end (line-end-position arg)))
(goto-char end)
(newline)
(insert (buffer-substring beg end))))
The string-repeat implementation can be rewritten as well:
(defun string-repeat (str n)
(apply ‘concat (make-list n str)))
I knew I’d learn something from posting this, thanks Ian. (I’m slightly surprised about identity as I thought I’d looked for it, but not about the rest).
A couple from my .emacs, first a bunch of string munging functions:
I also have a rather ugly “which” implementation which I’m sure could be nicer.
And finally the borrowed script that brings you the formatting of this posting.
Hi Alex,
Thanks for the list. I have a version of chomp that looks remarkably similar myself 🙂
And I found Ruslan’s nice htmlize snippet in a previous link round-up.
Cheers
Hi,
Reading your blog entry made me think I need a duplicate-current-line function, and one that works even when point is into last buffer’s line 🙂
I’m fond of elisp, some minutes later I’m enjoying this:
;; duplicate current line
(defun duplicate-current-line (&optional n)
“duplicate current line, make more than 1 copy given a numeric argument”
(interactive “p”)
(save-excursion
(let ((nb (or n 1))
(current-line (thing-at-point ‘line)))
;; when on last line, insert a newline first
(when (or (= 1 (forward-line 1)) (eq (point) (point-max)))
(insert “\n”))
;; now insert as many time as requested
(while (> n 0)
(insert current-line)
(setq n (- n 1))))))
(global-set-key (kbd “C-S-d”) ‘duplicate-current-line)
Hi dim,
Everyone should have a version of duplicate-current-line 😉 And I really should take one of these fixed version.
By the way, there is a dotimes macro in cl.el which you can use instead of your (while (> n 0) …)