This is part of the Emacs Starter Kit.
Function definitions
(require 'thingatpt)
(require 'imenu)
(defun set-font-from-list (fonts)
"Set font from FONTS list is available."
(when fonts
(let ((sfont nil))
(setq sfont (car fonts))
(if (member sfont (font-family-list))
(progn
(add-to-list 'initial-frame-alist '((font . sfont)))
(add-to-list 'default-frame-alist '((font . sfont)))
(set-face-attribute 'default nil :family sfont :height 180))
(setfont(cdr fonts))))
))
(defun ido-imenu ()
"Update the imenu index and then use ido to select a symbol to navigate to.
Symbols matching the text at point are put first in the completion list."
(interactive)
(imenu--make-index-alist)
(let ((name-and-pos '())
(symbol-names '()))
(cl-flet ((addsymbols (symbol-list)
(when (listp symbol-list)
(dolist (symbol symbol-list)
(let ((name nil) (position nil))
(cond
((and (listp symbol) (imenu--subalist-p symbol))
(addsymbols symbol))
((listp symbol)
(setq name (car symbol))
(setq position (cdr symbol)))
((stringp symbol)
(setq name symbol)
(setq position (get-text-property 1 'org-imenu-marker symbol))))
(unless (or (null position) (null name))
(add-to-list 'symbol-names name)
(add-to-list 'name-and-pos (cons name position))))))))
(addsymbols imenu--index-alist))
;; If there are matching symbols at point, put them at the beginning of `symbol-names'.
(let ((symbol-at-point (thing-at-point 'symbol)))
(when symbol-at-point
(let* ((regexp (concat (regexp-quote symbol-at-point) "$"))
(matching-symbols (delq nil (mapcar (lambda (symbol)
(if (string-match regexp symbol) symbol))
symbol-names))))
(when matching-symbols
(sort matching-symbols (lambda (a b) (> (length a) (length b))))
(mapc (lambda (symbol) (setq symbol-names (cons symbol (delete symbol symbol-names))))
matching-symbols)))))
(let* ((selected-symbol (ido-completing-read "Symbol? " symbol-names))
(position (cdr (assoc selected-symbol name-and-pos))))
(goto-char position))))
We have a number of turn-on-* functions since it’s advised that lambda functions not go in hooks. Repeatedly evaling an add-to-list with a hook value will repeatedly add it since there’s no way to ensure that a lambda doesn’t already exist in the list.
(defun local-comment-auto-fill ()
(set (make-local-variable 'comment-auto-fill-only-comments) t)
(auto-fill-mode t))
(defun turn-on-hl-line-mode ()
(if window-system (hl-line-mode t)))
(defun turn-on-save-place-mode ()
(setq save-place t))
(defun turn-on-whitespace ()
(whitespace-mode t))
(defun turn-on-semantic ()
((global-semantic-idle-scheduler-mode)
(global-semantic-idle-completions-mode)
(global-semantic-decoration-mode)
(global-semantic-highlight-func-mode)
(global-semantic-show-unmatched-syntax-mode)))
(defun untabify-buffer ()
(interactive)
(untabify (point-min) (point-max)))
(defun indent-buffer ()
(interactive)
(indent-region (point-min) (point-max)))
(defun cleanup-buffer ()
"Perform a bunch of operations on the whitespace content of a buffer."
(interactive)
(untabify-buffer)
(delete-trailing-whitespace))
(defun cleanup-buffer-hook ()
"A hook for cleanup-buffer. cleanup-buffer-modes should be a list
of modes you want the cleanup-buffer function applied to routinely. "
(when (member major-mode cleanup-buffer-modes)
(cleanup-buffer)))
;; now files int he modes listed in cleanup-buffer-mode will be
;; automatically cleaned every time they are saved.
(add-hook 'before-save-hook 'cleanup-buffer-hook)
(setq cleanup-buffer-modes
'(haskell-mode emacs-lisp-mode lisp-mode scheme-mode python-mode js2-mode web-mode ng2-ts-mode
erlang-mode clojure-mode ruby-mode scala-mode haskell-mode))
(defun recentf-ido-find-file ()
"Find a recent file using Ido."
(interactive)
(let* ((file-assoc-list (mapcar (lambda (x) (cons (file-name-nondirectory x) x)) recentf-list))
(filename-list (remove-duplicates (mapcar #'car file-assoc-list) :test #'string=))
(filename (ido-completing-read "Choose recent file: " filename-list nil t)))
(when filename
(find-file (cdr (assoc filename file-assoc-list))))))
(defun duplicate-line()
(interactive)
(move-beginning-of-line 1)
(kill-line)
(yank)
(open-line 1)
(next-line 1)
(yank))
(defun delete-word (arg)
"Delete characters backward until encountering the beginning of a word.
With argument ARG, do this that many times."
(interactive "p")
(delete-region (point) (progn (forward-word arg) (point))))
(defun backward-delete-word (arg)
"Delete characters backward until encountering the beginning of a word.
With argument, do this that many times.
This command does not push erased text to kill-ring."
(interactive "p")
(delete-word (- arg)))
(defun copy-line-or-region ()
"Copy current line, or current text selection."
(interactive)
(if (region-active-p)
(kill-ring-save (region-beginning) (region-end))
(kill-ring-save (line-beginning-position) (line-beginning-position 2))))
(defun copy-word ()
(interactive)
(kill-new (thing-at-point 'sexp)))
(require 'find-file-in-project)
(require 's)
;; No need to be stingy
(setq ffip-limit 4096)
;; Use full project path for ffip
(defun ffip-project-files ()
"Return an alist of all filenames in the project and their path."
(let ((file-alist nil))
(mapcar (lambda (file)
(let ((file-cons (cons (s-chop-prefix (file-truename (ffip-project-root)) (expand-file-name file))
(expand-file-name file))))
(add-to-list 'file-alist file-cons)
file-cons))
(split-string (shell-command-to-string
(format "find %s -type f \\( %s \\) %s | head -n %s"
(or ffip-project-root
(ffip-project-root)
(error "No project root found"))
(ffip-join-patterns)
ffip-find-options
ffip-limit))))))
(defun ffip-create-exclude-find-options (names)
(mapconcat (lambda (name) (concat "-not -regex \".*" name ".*\"")) names " "))
(defun ffip-local-excludes (&rest names)
"Given a set of names, will exclude results with those names in the path."
(set (make-local-variable 'ffip-find-options)
(ffip-create-exclude-find-options names)))
(defun ffip-local-patterns (&rest patterns)
"An exhaustive list of file name patterns to look for."
(set (make-local-variable 'ffip-patterns) patterns))
;; Function to create new functions that look for a specific pattern
(defun ffip-create-pattern-file-finder (&rest patterns)
(lexical-let ((patterns patterns))
(lambda ()
(interactive)
(let ((ffip-patterns patterns))
(find-file-in-project)))))
;; Default excludes - override with ffip-local-excludes
(setq-default ffip-find-options
(ffip-create-exclude-find-options
'("/node_modules"
"/target"
"/out"
"/overlays"
"/build"
"/dist"
"/vendor"
"/.cask"
"/generated"
"/.repl")))
(provide 'setup-ffip)
(defmacro project-specifics (name &rest body)
`(progn
(add-hook 'find-file-hook (lambda () (when (string-match-p, name (buffer-file-name)), body)))
(add-hook 'dired-after-readin-hook (lambda () (when (string-match-p, name (dired-current-directory)), body)))))
(defvar mode-line-cleaner-alist
`((auto-complete-mode . " α")
(yas/minor-mode . " υ")
(paredit-mode . " π")
(company-mode . " c")
(projectile-mode . " Ȝ")
;; (eldoc-mode . "")
(abbrev-mode . "")
(visual-line-mode . "")
(color-identifiers-mode . "")
(whitespace-mode . "")
(undo-tree-mode . "")
(auto-fill-mode . "")
;; Major modes
(lisp-interaction-mode . "λ")
(hi-lock-mode . "")
(python-mode . "ƿ")
(emacs-lisp-mode . "EL")
(nxhtml-mode . "nx"))
"Alist for `clean-mode-line'.
When you add a new element to the alist, keep in mind that you
must pass the correct minor/major mode symbol and a string you
want to use in the modeline *in lieu of* the original.")
(defun clean-mode-line ()
(interactive)
(loop for cleaner in mode-line-cleaner-alist
do (let* ((mode (car cleaner))
(mode-str (cdr cleaner))
(old-mode-str (cdr (assq mode minor-mode-alist))))
(when old-mode-str
(setcar old-mode-str mode-str))
;; major mode
(when (eq mode major-mode)
(setq mode-name mode-str)))))
(add-hook 'after-change-major-mode-hook 'clean-mode-line)
(defun sudo-shell-command (command)
(interactive "MShell command (root): ")
(with-temp-buffer
(cd "/sudo::/")
(async-shell-command command)))
(message "------ Starter Kit Defun loaded ------")