Emacs config utilizing prelude as a base
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

419 lines
14 KiB

14 years ago
  1. ;;; prelude-core.el --- Emacs Prelude: core Prelude defuns.
  2. ;;
  3. ;; Copyright (c) 2011 Bozhidar Batsov
  4. ;;
  5. ;; Author: Bozhidar Batsov <bozhidar.batsov@gmail.com>
  6. ;; URL: http://www.emacswiki.org/cgi-bin/wiki/Prelude
  7. ;; Version: 1.0.0
  8. ;; Keywords: convenience
  9. ;; This file is not part of GNU Emacs.
  10. ;;; Commentary:
  11. ;; Here are the definitions of most of the functions added by Prelude.
  12. ;;; License:
  13. ;; This program is free software; you can redistribute it and/or
  14. ;; modify it under the terms of the GNU General Public License
  15. ;; as published by the Free Software Foundation; either version 3
  16. ;; of the License, or (at your option) any later version.
  17. ;;
  18. ;; This program is distributed in the hope that it will be useful,
  19. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. ;; GNU General Public License for more details.
  22. ;;
  23. ;; You should have received a copy of the GNU General Public License
  24. ;; along with GNU Emacs; see the file COPYING. If not, write to the
  25. ;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  26. ;; Boston, MA 02110-1301, USA.
  27. ;;; Code:
  28. (require 'cl)
  29. (require 'thingatpt)
  30. (require 'imenu)
  31. (defun prelude-add-subfolders-to-load-path (parent-dir)
  32. "Adds all first level `parent-dir' subdirs to the
  33. Emacs load path."
  34. (dolist (f (directory-files parent-dir))
  35. (let ((name (concat parent-dir f)))
  36. (when (and (file-directory-p name)
  37. (not (equal f ".."))
  38. (not (equal f ".")))
  39. (add-to-list 'load-path name)))))
  40. ;; add the first level subfolders of vendor automatically
  41. (prelude-add-subfolders-to-load-path vendor-dir)
  42. (defun prelude-open-with ()
  43. "Simple function that allows us to open the underlying
  44. file of a buffer in an external program."
  45. (interactive)
  46. (when buffer-file-name
  47. (shell-command (concat
  48. (read-shell-command "Open current file with: ")
  49. " "
  50. buffer-file-name))))
  51. (defun prelude-buffer-mode (buffer-or-name)
  52. (with-current-buffer buffer-or-name major-mode))
  53. (defun prelude-visit-term-buffer ()
  54. (interactive)
  55. (if (not (get-buffer "*ansi-term*"))
  56. (ansi-term "/bin/bash")
  57. (switch-to-buffer "*ansi-term*")))
  58. (defun prelude-google ()
  59. "Googles a query or region if any."
  60. (interactive)
  61. (browse-url
  62. (concat
  63. "http://www.google.com/search?ie=utf-8&oe=utf-8&q="
  64. (if mark-active
  65. (buffer-substring (region-beginning) (region-end))
  66. (read-string "Google: ")))))
  67. (defun prelude-indent-rigidly-and-copy-to-clipboard (begin end indent)
  68. "Copy the selected code region to the clipboard, indented according
  69. to Markdown blockquote rules."
  70. (let ((buffer (current-buffer)))
  71. (with-temp-buffer
  72. (insert-buffer-substring-no-properties buffer begin end)
  73. (indent-rigidly (point-min) (point-max) indent)
  74. (clipboard-kill-ring-save (point-min) (point-max)))))
  75. (defun prelude-indent-blockquote-and-copy-to-clipboard (begin end)
  76. "Copy the selected code region to the clipboard, indented according
  77. to markdown blockquote rules (useful to copy snippets to StackOverflow, Assembla, Github."
  78. (interactive "r")
  79. (prelude-indent-rigidly-and-copy-to-clipboard begin end 4))
  80. (defun prelude-indent-nested-blockquote-and-copy-to-clipboard (begin end)
  81. "Copy the selected code region to the clipboard, indented according
  82. to markdown blockquote rules. Useful to add snippets under bullet points."
  83. (interactive "r")
  84. (prelude-indent-rigidly-and-copy-to-clipboard begin end 6))
  85. (defun prelude-insert-empty-line ()
  86. "Insert an empty line after the current line and positon
  87. the curson at its beginning, according to the current mode."
  88. (interactive)
  89. (move-end-of-line nil)
  90. (open-line 1)
  91. (next-line 1)
  92. (indent-according-to-mode))
  93. ;; mimic popular IDEs binding, note that it doesn't work in a terminal session
  94. (global-set-key [(shift return)] 'prelude-insert-empty-line)
  95. (defun prelude-move-line-up ()
  96. "Move up the current line."
  97. (interactive)
  98. (transpose-lines 1)
  99. (previous-line 2))
  100. (global-set-key [(control shift up)] 'prelude-move-line-up)
  101. (defun prelude-move-line-down ()
  102. "Move down the current line."
  103. (interactive)
  104. (next-line 1)
  105. (transpose-lines 1)
  106. (previous-line 1))
  107. (global-set-key [(control shift down)] 'prelude-move-line-down)
  108. ;; add the ability to copy and cut the current line, without marking it
  109. (defadvice kill-ring-save (before slick-copy activate compile)
  110. "When called interactively with no active region, copy a single line instead."
  111. (interactive
  112. (if mark-active (list (region-beginning) (region-end))
  113. (message "Copied line")
  114. (list (line-beginning-position)
  115. (line-beginning-position 2)))))
  116. (defadvice kill-region (before slick-cut activate compile)
  117. "When called interactively with no active region, kill a single line instead."
  118. (interactive
  119. (if mark-active (list (region-beginning) (region-end))
  120. (list (line-beginning-position)
  121. (line-beginning-position 2)))))
  122. (defun prelude-indent-buffer ()
  123. "Indents the entire buffer."
  124. (interactive)
  125. (indent-region (point-min) (point-max)))
  126. (defun prelude-indent-region-or-buffer ()
  127. "Indents a region if selected, otherwise the whole buffer."
  128. (interactive)
  129. (save-excursion
  130. (if (region-active-p)
  131. (progn
  132. (indent-region (region-beginning) (region-end))
  133. (message "Indented selected region."))
  134. (progn
  135. (prelude-indent-buffer)
  136. (message "Indented buffer.")))))
  137. (defun prelude-annotate-todo ()
  138. "Put fringe marker on TODO: lines in the curent buffer."
  139. (interactive)
  140. (save-excursion
  141. (goto-char (point-min))
  142. (while (re-search-forward "TODO:" nil t)
  143. (let ((overlay (make-overlay (- (point) 5) (point))))
  144. (overlay-put overlay
  145. 'before-string
  146. (propertize (format "A")
  147. 'display '(left-fringe right-triangle)))))))
  148. (defun prelude-copy-file-name-to-clipboard ()
  149. "Put the current file name on the clipboard."
  150. (interactive)
  151. (let ((filename (if (equal major-mode 'dired-mode)
  152. default-directory
  153. (buffer-file-name))))
  154. (when filename
  155. (with-temp-buffer
  156. (insert filename)
  157. (clipboard-kill-region (point-min) (point-max)))
  158. (message filename))))
  159. (defun prelude-duplicate-current-line-or-region (arg)
  160. "Duplicates the current line or region ARG times.
  161. If there's no region, the current line will be duplicated. However, if
  162. there's a region, all lines that region covers will be duplicated."
  163. (interactive "p")
  164. (let (beg end (origin (point)))
  165. (if (and mark-active (> (point) (mark)))
  166. (exchange-point-and-mark))
  167. (setq beg (line-beginning-position))
  168. (if mark-active
  169. (exchange-point-and-mark))
  170. (setq end (line-end-position))
  171. (let ((region (buffer-substring-no-properties beg end)))
  172. (dotimes (i arg)
  173. (goto-char end)
  174. (newline)
  175. (insert region)
  176. (setq end (point)))
  177. (goto-char (+ origin (* (length region) arg) arg)))))
  178. ;; TODO doesn't work with uniquify
  179. (defun prelude-rename-file-and-buffer ()
  180. "Renames current buffer and file it is visiting."
  181. (interactive)
  182. (let ((name (buffer-name))
  183. (filename (buffer-file-name)))
  184. (if (not (and filename (file-exists-p filename)))
  185. (message "Buffer '%s' is not visiting a file!" name)
  186. (let ((new-name (read-file-name "New name: " filename)))
  187. (cond ((get-buffer new-name)
  188. (message "A buffer named '%s' already exists!" new-name))
  189. (t
  190. (rename-file name new-name 1)
  191. (rename-buffer new-name)
  192. (set-visited-file-name new-name)
  193. (set-buffer-modified-p nil)))))))
  194. (defun prelude-delete-file-and-buffer ()
  195. "Kills the current buffer and deletes the file it is visiting"
  196. (interactive)
  197. (let ((filename (buffer-file-name)))
  198. (when filename
  199. (delete-file filename)
  200. (message "Deleted file %s" filename)))
  201. (kill-buffer))
  202. (defun prelude-view-url ()
  203. "Open a new buffer containing the contents of URL."
  204. (interactive)
  205. (let* ((default (thing-at-point-url-at-point))
  206. (url (read-from-minibuffer "URL: " default)))
  207. (switch-to-buffer (url-retrieve-synchronously url))
  208. (rename-buffer url t)
  209. ;; TODO: switch to nxml/nxhtml mode
  210. (cond ((search-forward "<?xml" nil t) (xml-mode))
  211. ((search-forward "<html" nil t) (html-mode)))))
  212. (defun prelude-ido-goto-symbol (&optional symbol-list)
  213. "Refresh imenu and jump to a place in the buffer using Ido."
  214. (interactive)
  215. (unless (featurep 'imenu)
  216. (require 'imenu nil t))
  217. (cond
  218. ((not symbol-list)
  219. (let ((ido-mode ido-mode)
  220. (ido-enable-flex-matching
  221. (if (boundp 'ido-enable-flex-matching)
  222. ido-enable-flex-matching t))
  223. name-and-pos symbol-names position)
  224. (unless ido-mode
  225. (ido-mode 1)
  226. (setq ido-enable-flex-matching t))
  227. (while (progn
  228. (imenu--cleanup)
  229. (setq imenu--index-alist nil)
  230. (ido-goto-symbol (imenu--make-index-alist))
  231. (setq selected-symbol
  232. (ido-completing-read "Symbol? " symbol-names))
  233. (string= (car imenu--rescan-item) selected-symbol)))
  234. (unless (and (boundp 'mark-active) mark-active)
  235. (push-mark nil t nil))
  236. (setq position (cdr (assoc selected-symbol name-and-pos)))
  237. (cond
  238. ((overlayp position)
  239. (goto-char (overlay-start position)))
  240. (t
  241. (goto-char position)))))
  242. ((listp symbol-list)
  243. (dolist (symbol symbol-list)
  244. (let (name position)
  245. (cond
  246. ((and (listp symbol) (imenu--subalist-p symbol))
  247. (ido-goto-symbol symbol))
  248. ((listp symbol)
  249. (setq name (car symbol))
  250. (setq position (cdr symbol)))
  251. ((stringp symbol)
  252. (setq name symbol)
  253. (setq position
  254. (get-text-property 1 'org-imenu-marker symbol))))
  255. (unless (or (null position) (null name)
  256. (string= (car imenu--rescan-item) name))
  257. (add-to-list 'symbol-names name)
  258. (add-to-list 'name-and-pos (cons name position))))))))
  259. ;; We have a number of turn-on-* functions since it's advised that lambda
  260. ;; functions not go in hooks. Repeatedly evaluating an add-to-list with a
  261. ;; hook value will repeatedly add it since there's no way to ensure
  262. ;; that a lambda doesn't already exist in the list.
  263. (defun prelude-local-comment-auto-fill ()
  264. (set (make-local-variable 'comment-auto-fill-only-comments) t)
  265. (auto-fill-mode t))
  266. (defun prelude-turn-on-whitespace ()
  267. (whitespace-mode +1))
  268. (defun prelude-turn-off-whitespace ()
  269. (whitespace-mode -1))
  270. (defun prelude-turn-on-abbrev ()
  271. (abbrev-mode +1))
  272. (defun prelude-turn-off-abbrev ()
  273. (abbrev-mode -1))
  274. (defun prelude-add-watchwords ()
  275. (font-lock-add-keywords
  276. nil '(("\\<\\(FIX\\|TODO\\|FIXME\\|HACK\\|REFACTOR\\):"
  277. 1 font-lock-warning-face t))))
  278. (defun prelude-coding-hook ()
  279. "Default coding hook, useful with any programming language."
  280. (flyspell-prog-mode)
  281. (prelude-local-comment-auto-fill)
  282. (prelude-turn-on-whitespace)
  283. (prelude-turn-on-abbrev)
  284. (prelude-add-watchwords))
  285. (defun prelude-untabify-buffer ()
  286. (interactive)
  287. (untabify (point-min) (point-max)))
  288. (defun prelude-cleanup-buffer ()
  289. "Perform a bunch of operations on the whitespace content of a buffer."
  290. (interactive)
  291. (prelude-indent-buffer)
  292. (prelude-untabify-buffer)
  293. (delete-trailing-whitespace))
  294. (defun prelude-eval-and-replace ()
  295. "Replace the preceding sexp with its value."
  296. (interactive)
  297. (backward-kill-sexp)
  298. (condition-case nil
  299. (prin1 (eval (read (current-kill 0)))
  300. (current-buffer))
  301. (error (message "Invalid expression")
  302. (insert (current-kill 0)))))
  303. (defun prelude-recompile-init ()
  304. "Byte-compile all your dotfiles again."
  305. (interactive)
  306. (byte-recompile-directory prelude-dir 0)
  307. (byte-recompile-directory vendor-dir 0))
  308. (defun prelude-regen-autoloads (&optional force-regen)
  309. "Regenerate the autoload definitions file if necessary and load it."
  310. (interactive "P")
  311. (let ((autoload-dir vendor-dir)
  312. (generated-autoload-file autoload-file))
  313. (when (or force-regen
  314. (not (file-exists-p autoload-file))
  315. (some (lambda (f) (file-newer-than-file-p f autoload-file))
  316. (directory-files autoload-dir t "\\.el$")))
  317. (message "Updating autoloads...")
  318. (let (emacs-lisp-mode-hook)
  319. (update-directory-autoloads autoload-dir))))
  320. (load autoload-file))
  321. (defun prelude-sudo-edit (&optional arg)
  322. (interactive "p")
  323. (if (or arg (not buffer-file-name))
  324. (find-file (concat "/sudo:root@localhost:" (ido-read-file-name "File: ")))
  325. (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))
  326. (defun prelude-switch-or-start (function buffer)
  327. "If the buffer is current, bury it, otherwise invoke the function."
  328. (if (equal (buffer-name (current-buffer)) buffer)
  329. (bury-buffer)
  330. (if (get-buffer buffer)
  331. (switch-to-buffer buffer)
  332. (funcall function))))
  333. (defun prelude-insert-date ()
  334. "Insert a time-stamp according to locale's date and time format."
  335. (interactive)
  336. (insert (format-time-string "%c" (current-time))))
  337. (defun prelude-conditionally-enable-paredit-mode ()
  338. "Enable paredit-mode in the minibuffer, during eval-expression."
  339. (if (eq this-command 'eval-expression)
  340. (paredit-mode 1)))
  341. (add-hook 'minibuffer-setup-hook 'prelude-conditionally-enable-paredit-mode)
  342. (defun prelude-recentf-ido-find-file ()
  343. "Find a recent file using ido."
  344. (interactive)
  345. (let ((file (ido-completing-read "Choose recent file: " recentf-list nil t)))
  346. (when file
  347. (find-file file))))
  348. (defun prelude-swap-windows ()
  349. "If you have 2 windows, it swaps them."
  350. (interactive)
  351. (if (/= (count-windows) 2)
  352. (message "You need exactly 2 windows to do this.")
  353. (let* ((w1 (first (window-list)))
  354. (w2 (second (window-list)))
  355. (b1 (window-buffer w1))
  356. (b2 (window-buffer w2))
  357. (s1 (window-start w1))
  358. (s2 (window-start w2)))
  359. (set-window-buffer w1 b2)
  360. (set-window-buffer w2 b1)
  361. (set-window-start w1 s2)
  362. (set-window-start w2 s1)))
  363. (other-window 1))
  364. (provide 'prelude-core)
  365. ;;; prelude-core.el ends here