|
|
;;; prelude-core.el --- Emacs Prelude: core Prelude defuns.;;;; Copyright (c) 2011 Bozhidar Batsov;;;; Author: Bozhidar Batsov <bozhidar.batsov@gmail.com>;; URL: http://www.emacswiki.org/cgi-bin/wiki/Prelude;; Version: 1.0.0;; Keywords: convenience
;; This file is not part of GNU Emacs.
;;; Commentary:
;; Here are the definitions of most of the functions added by Prelude.
;;; License:
;; This program is free software; you can redistribute it and/or;; modify it under the terms of the GNU General Public License;; as published by the Free Software Foundation; either version 3;; of the License, or (at your option) any later version.;;;; This program is distributed in the hope that it will be useful,;; but WITHOUT ANY WARRANTY; without even the implied warranty of;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the;; GNU General Public License for more details.;;;; You should have received a copy of the GNU General Public License;; along with GNU Emacs; see the file COPYING. If not, write to the;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,;; Boston, MA 02110-1301, USA.
;;; Code:
(require 'cl)(require 'thingatpt)(require 'imenu)
(defun prelude-add-subfolders-to-load-path (parent-dir) "Adds all first level `parent-dir' subdirs to the
Emacs load path."
(dolist (f (directory-files parent-dir)) (let ((name (concat parent-dir f))) (when (and (file-directory-p name) (not (equal f "..")) (not (equal f "."))) (add-to-list 'load-path name)))))
;; add the first level subfolders of vendor automatically(prelude-add-subfolders-to-load-path prelude-vendor-dir)
(defun prelude-open-with () "Simple function that allows us to open the underlying
file of a buffer in an external program."
(interactive) (when buffer-file-name (shell-command (concat (if (eq system-type 'darwin) "open" (read-shell-command "Open current file with: ")) " " buffer-file-name))))
(defun prelude-buffer-mode (buffer-or-name) (with-current-buffer buffer-or-name major-mode))
(defun prelude-visit-term-buffer () (interactive) (if (not (get-buffer "*ansi-term*")) (ansi-term "/bin/bash") (switch-to-buffer "*ansi-term*")))
(defun prelude-google () "Googles a query or region if any." (interactive) (browse-url (concat "http://www.google.com/search?ie=utf-8&oe=utf-8&q=" (if mark-active (buffer-substring (region-beginning) (region-end)) (read-string "Google: ")))))
(defun prelude-indent-rigidly-and-copy-to-clipboard (begin end indent) "Copy the selected code region to the clipboard, indented according
to Markdown blockquote rules."
(let ((buffer (current-buffer))) (with-temp-buffer (insert-buffer-substring-no-properties buffer begin end) (indent-rigidly (point-min) (point-max) indent) (clipboard-kill-ring-save (point-min) (point-max)))))
(defun prelude-indent-blockquote-and-copy-to-clipboard (begin end) "Copy the selected code region to the clipboard, indented according
to markdown blockquote rules (useful to copy snippets to StackOverflow, Assembla, Github."
(interactive "r") (prelude-indent-rigidly-and-copy-to-clipboard begin end 4))
(defun prelude-indent-nested-blockquote-and-copy-to-clipboard (begin end) "Copy the selected code region to the clipboard, indented according
to markdown blockquote rules. Useful to add snippets under bullet points."
(interactive "r") (prelude-indent-rigidly-and-copy-to-clipboard begin end 6))
(defun prelude-insert-empty-line () "Insert an empty line after the current line and positon
the curson at its beginning, according to the current mode."
(interactive) (move-end-of-line nil) (open-line 1) (next-line 1) (indent-according-to-mode))
;; mimic popular IDEs binding, note that it doesn't work in a terminal session(global-set-key [(shift return)] 'prelude-insert-empty-line)
(defun prelude-move-line-up () "Move up the current line." (interactive) (transpose-lines 1) (previous-line 2))
(global-set-key [(control shift up)] 'prelude-move-line-up)
(defun prelude-move-line-down () "Move down the current line." (interactive) (next-line 1) (transpose-lines 1) (previous-line 1))
(global-set-key [(control shift down)] 'prelude-move-line-down)
;; add the ability to copy and cut the current line, without marking it(defadvice kill-ring-save (before slick-copy activate compile) "When called interactively with no active region, copy a single line instead." (interactive (if mark-active (list (region-beginning) (region-end)) (message "Copied line") (list (line-beginning-position) (line-beginning-position 2)))))
(defadvice kill-region (before slick-cut activate compile) "When called interactively with no active region, kill a single line instead." (interactive (if mark-active (list (region-beginning) (region-end)) (list (line-beginning-position) (line-beginning-position 2)))))
(defun prelude-indent-buffer () "Indents the entire buffer." (interactive) (indent-region (point-min) (point-max)))
(defun prelude-indent-region-or-buffer () "Indents a region if selected, otherwise the whole buffer." (interactive) (save-excursion (if (region-active-p) (progn (indent-region (region-beginning) (region-end)) (message "Indented selected region.")) (progn (prelude-indent-buffer) (message "Indented buffer.")))))
(defun prelude-annotate-todo () "Put fringe marker on TODO: lines in the curent buffer." (interactive) (save-excursion (goto-char (point-min)) (while (re-search-forward "TODO:" nil t) (let ((overlay (make-overlay (- (point) 5) (point)))) (overlay-put overlay 'before-string (propertize (format "A") 'display '(left-fringe right-triangle)))))))
(defun prelude-copy-file-name-to-clipboard () "Put the current file name on the clipboard." (interactive) (let ((filename (if (equal major-mode 'dired-mode) default-directory (buffer-file-name)))) (when filename (with-temp-buffer (insert filename) (clipboard-kill-region (point-min) (point-max))) (message filename))))
(defun prelude-duplicate-current-line-or-region (arg) "Duplicates the current line or region ARG times.
If there's no region, the current line will be duplicated. However, ifthere's a region, all lines that region covers will be duplicated."
(interactive "p") (let (beg end (origin (point))) (if (and mark-active (> (point) (mark))) (exchange-point-and-mark)) (setq beg (line-beginning-position)) (if mark-active (exchange-point-and-mark)) (setq end (line-end-position)) (let ((region (buffer-substring-no-properties beg end))) (dotimes (i arg) (goto-char end) (newline) (insert region) (setq end (point))) (goto-char (+ origin (* (length region) arg) arg)))))
;; TODO doesn't work with uniquify(defun prelude-rename-file-and-buffer () "Renames current buffer and file it is visiting." (interactive) (let ((name (buffer-name)) (filename (buffer-file-name))) (if (not (and filename (file-exists-p filename))) (message "Buffer '%s' is not visiting a file!" name) (let ((new-name (read-file-name "New name: " filename))) (cond ((get-buffer new-name) (message "A buffer named '%s' already exists!" new-name)) (t (rename-file name new-name 1) (rename-buffer new-name) (set-visited-file-name new-name) (set-buffer-modified-p nil)))))))
(defun prelude-delete-file-and-buffer () "Kills the current buffer and deletes the file it is visiting" (interactive) (let ((filename (buffer-file-name))) (when filename (delete-file filename) (message "Deleted file %s" filename))) (kill-buffer))
(defun prelude-view-url () "Open a new buffer containing the contents of URL." (interactive) (let* ((default (thing-at-point-url-at-point)) (url (read-from-minibuffer "URL: " default))) (switch-to-buffer (url-retrieve-synchronously url)) (rename-buffer url t) ;; TODO: switch to nxml/nxhtml mode (cond ((search-forward "<?xml" nil t) (xml-mode)) ((search-forward "<html" nil t) (html-mode)))))
(defun prelude-ido-goto-symbol (&optional symbol-list) "Refresh imenu and jump to a place in the buffer using Ido." (interactive) (unless (featurep 'imenu) (require 'imenu nil t)) (cond ((not symbol-list) (let ((ido-mode ido-mode) (ido-enable-flex-matching (if (boundp 'ido-enable-flex-matching) ido-enable-flex-matching t)) name-and-pos symbol-names position) (unless ido-mode (ido-mode 1) (setq ido-enable-flex-matching t)) (while (progn (imenu--cleanup) (setq imenu--index-alist nil) (prelude-ido-goto-symbol (imenu--make-index-alist)) (setq selected-symbol (ido-completing-read "Symbol? " symbol-names)) (string= (car imenu--rescan-item) selected-symbol))) (unless (and (boundp 'mark-active) mark-active) (push-mark nil t nil)) (setq position (cdr (assoc selected-symbol name-and-pos))) (cond ((overlayp position) (goto-char (overlay-start position))) (t (goto-char position))))) ((listp symbol-list) (dolist (symbol symbol-list) (let (name position) (cond ((and (listp symbol) (imenu--subalist-p symbol)) (prelude-ido-goto-symbol 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) (string= (car imenu--rescan-item) name)) (add-to-list 'symbol-names name) (add-to-list 'name-and-pos (cons name position))))))))
;; We have a number of turn-on-* functions since it's advised that lambda;; functions not go in hooks. Repeatedly evaluating 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 prelude-local-comment-auto-fill () (set (make-local-variable 'comment-auto-fill-only-comments) t) (auto-fill-mode t))
(defun prelude-turn-on-whitespace () (whitespace-mode +1))
(defun prelude-turn-off-whitespace () (whitespace-mode -1))
(defun prelude-turn-on-abbrev () (abbrev-mode +1))
(defun prelude-turn-off-abbrev () (abbrev-mode -1))
(defun prelude-add-watchwords () (font-lock-add-keywords nil '(("\\<\\(FIX\\|TODO\\|FIXME\\|HACK\\|REFACTOR\\):" 1 font-lock-warning-face t))))
(defun prelude-prog-mode-hook () "Default coding hook, useful with any programming language." (flyspell-prog-mode) (prelude-local-comment-auto-fill) (prelude-turn-on-whitespace) (prelude-turn-on-abbrev) (prelude-add-watchwords) ;; keep the whitespace decent all the time (add-hook 'before-save-hook 'whitespace-cleanup nil t))
;; in Emacs 24 programming major modes generally derive;; from a common mode named prog-mode(add-hook 'prog-mode-hook 'prelude-prog-mode-hook)
(defun prelude-untabify-buffer () (interactive) (untabify (point-min) (point-max)))
(defun prelude-cleanup-buffer () "Perform a bunch of operations on the whitespace content of a buffer." (interactive) (prelude-indent-buffer) (prelude-untabify-buffer) (whitespace-cleanup))
(defun prelude-eval-and-replace () "Replace the preceding sexp with its value." (interactive) (backward-kill-sexp) (condition-case nil (prin1 (eval (read (current-kill 0))) (current-buffer)) (error (message "Invalid expression") (insert (current-kill 0)))))
(defun prelude-recompile-init () "Byte-compile all your dotfiles again." (interactive) (byte-recompile-directory prelude-dir 0) (byte-recompile-directory prelude-vendor-dir 0))
(defun prelude-regen-autoloads (&optional force-regen) "Regenerate the autoload definitions file if necessary and load it." (interactive "P") (let ((autoload-dir prelude-vendor-dir) (generated-autoload-file autoload-file)) (when (or force-regen (not (file-exists-p autoload-file)) (some (lambda (f) (file-newer-than-file-p f autoload-file)) (directory-files autoload-dir t "\\.el$"))) (message "Updating autoloads...") (let (emacs-lisp-mode-hook) (update-directory-autoloads autoload-dir)))) (load autoload-file))
(defun prelude-sudo-edit (&optional arg) (interactive "p") (if (or arg (not buffer-file-name)) (find-file (concat "/sudo:root@localhost:" (ido-read-file-name "File: "))) (find-alternate-file (concat "/sudo:root@localhost:" buffer-file-name))))
(defun prelude-switch-or-start (function buffer) "If the buffer is current, bury it, otherwise invoke the function." (if (equal (buffer-name (current-buffer)) buffer) (bury-buffer) (if (get-buffer buffer) (switch-to-buffer buffer) (funcall function))))
(defun prelude-insert-date () "Insert a time-stamp according to locale's date and time format." (interactive) (insert (format-time-string "%c" (current-time))))
(defun prelude-conditionally-enable-paredit-mode () "Enable paredit-mode in the minibuffer, during eval-expression." (if (eq this-command 'eval-expression) (paredit-mode 1)))
(add-hook 'minibuffer-setup-hook 'prelude-conditionally-enable-paredit-mode)
(defun prelude-recentf-ido-find-file () "Find a recent file using ido." (interactive) (let ((file (ido-completing-read "Choose recent file: " recentf-list nil t))) (when file (find-file file))))
(defun prelude-swap-windows () "If you have 2 windows, it swaps them." (interactive) (if (/= (count-windows) 2) (message "You need exactly 2 windows to do this.") (let* ((w1 (first (window-list))) (w2 (second (window-list))) (b1 (window-buffer w1)) (b2 (window-buffer w2)) (s1 (window-start w1)) (s2 (window-start w2))) (set-window-buffer w1 b2) (set-window-buffer w2 b1) (set-window-start w1 s2) (set-window-start w2 s1))) (other-window 1))
(provide 'prelude-core);;; prelude-core.el ends here
|