This repository has been archived on 2024-10-22. You can view files and clone it, but cannot push or open issues or pull requests.
spacemacs/layers/!distribution/spacemacs-core/funcs.el
2015-09-11 00:02:22 -04:00

922 lines
32 KiB
EmacsLisp

;;; funcs.el --- Spacemacs Core Layer functions File
;;
;; Copyright (c) 2012-2014 Sylvain Benner
;; Copyright (c) 2014-2015 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;;; License: GPLv3
;; add emacs binary helper functions
(defun spacemacs/emacsbin-path ()
(interactive)
(concat exec-directory (if (spacemacs/system-is-mswindows) "bin/") "emacs"))
(defun spacemacs/emacs-start ()
(interactive)
(call-process (spacemacs/emacsbin-path) nil 0 nil)
(message "Started 'emacs' - it will be ready soon ..."))
(defun spacemacs/emacs-debug-init ()
(interactive)
(call-process (spacemacs/emacsbin-path) nil 0 nil "--debug-init")
(message "Started 'emacs --debug-init' - it will be ready soon ..."))
(defun spacemacs/emacs-reload ()
(interactive)
(load-file user-init-file)
(message ".emacs reloaded successfully"))
(defun spacemacs/emacs-Q ()
(interactive)
(call-process (spacemacs/emacsbin-path) nil 0 nil "-Q")
(message "Started 'emacs -Q' - it will be ready soon ..."))
;; from https://github.com/cofi/dotfiles/blob/master/emacs.d/config/cofi-util.el#L38
(defun spacemacs/add-to-hooks (fun hooks)
"Add function to hooks"
(dolist (hook hooks)
(add-hook hook fun)))
(defun spacemacs/add-all-to-hook (hook &rest funs)
"Add functions to hook."
(spacemacs/add-to-hook hook funs))
(defun spacemacs/add-to-hook (hook funs)
"Add list of functions to hook."
(dolist (fun funs)
(add-hook hook fun)))
(defun spacemacs/echo (msg &rest args)
"Display MSG in echo-area without logging it in *Messages* buffer."
(interactive)
(let ((message-log-max nil))
(apply 'message msg args)))
(defun spacemacs/system-is-mac ()
(string-equal system-type "darwin"))
(defun spacemacs/system-is-linux ()
(string-equal system-type "gnu/linux"))
(defun spacemacs/system-is-mswindows ()
(string-equal system-type "windows-nt"))
(defvar spacemacs/prefix-command-string "group:"
"Prefix string for prefix commands.")
(defvar spacemacs/prefix-titles (list))
(defun spacemacs/jump-in-buffer ()
(interactive)
(cond
((eq major-mode 'org-mode)
(call-interactively 'helm-org-in-buffer-headings))
(t
(call-interactively 'helm-semantic-or-imenu))))
(defun spacemacs/declare-prefix (prefix name &optional long-name)
"Declare a prefix PREFIX. PREFIX is a string describing a key
sequence. NAME is a symbol name used as the prefix command.
LONG-NAME if given is stored in `spacemacs/prefix-command-alist'."
(let* ((command (intern (concat spacemacs/prefix-command-string name)))
(full-prefix (concat dotspacemacs-leader-key " " prefix))
(full-prefix-emacs (concat dotspacemacs-emacs-leader-key " " prefix))
(full-prefix-lst (listify-key-sequence (kbd full-prefix)))
(full-prefix-emacs-lst (listify-key-sequence
(kbd full-prefix-emacs))))
;; define the prefix command only if it does not already exist
(unless long-name (setq long-name name))
(if (fboundp 'which-key-declare-prefixes)
(which-key-declare-prefixes
full-prefix-emacs (cons name long-name)
full-prefix (cons name long-name))
(unless (lookup-key evil-leader--default-map prefix)
(define-prefix-command command)
(evil-leader/set-key prefix command)
(push (cons full-prefix-lst long-name) spacemacs/prefix-titles)
(push (cons full-prefix-emacs-lst long-name) spacemacs/prefix-titles)))))
(defun spacemacs/declare-prefix-for-mode (mode prefix name &optional long-name)
"Declare a prefix PREFIX. MODE is the mode in which this prefix command should
be added. PREFIX is a string describing a key sequence. NAME is a symbol name
used as the prefix command."
(let ((command (intern (concat spacemacs/prefix-command-string name)))
(full-prefix (concat dotspacemacs-leader-key " " prefix))
(full-prefix-emacs (concat dotspacemacs-emacs-leader-key " " prefix)))
(unless long-name (setq long-name name))
(if (fboundp 'which-key-declare-prefixes-for-mode)
(which-key-declare-prefixes-for-mode mode
full-prefix-emacs (cons name long-name)
full-prefix (cons name long-name))
(define-prefix-command command)
(evil-leader/set-key-for-mode mode prefix command))))
(defun spacemacs/activate-major-mode-leader ()
"Bind major mode key map to `dotspacemacs-major-mode-leader-key'."
(setq mode-map (cdr (assoc major-mode evil-leader--mode-maps)))
(when mode-map
(setq major-mode-map (lookup-key mode-map (kbd "m")))
(mapc (lambda (s)
(eval `(define-key
,(intern (format "evil-%S-state-local-map" s))
,(kbd dotspacemacs-major-mode-leader-key)
major-mode-map)))
'(normal motion))
(mapc (lambda (s)
(eval `(define-key
,(intern (format "evil-%S-state-local-map" s))
,(kbd dotspacemacs-major-mode-emacs-leader-key)
major-mode-map)))
'(emacs insert normal motion visual))
(when hybrid-mode
(define-key evil-hybrid-state-map
(kbd dotspacemacs-major-mode-emacs-leader-key)
major-mode-map))))
(defun spacemacs/split-and-new-line ()
"Split a quoted string or s-expression and insert a new line with
auto-indent."
(interactive)
(sp-split-sexp 1)
(sp-newline))
(defun spacemacs/push-mark-and-goto-beginning-of-line ()
"Push a mark at current location and go to the beginnign of the line."
(interactive)
(push-mark (point))
(evil-beginning-of-line))
(defun spacemacs/push-mark-and-goto-end-of-line ()
"Push a mark at current location and go to the end of the line."
(interactive)
(push-mark (point))
(evil-end-of-line))
;; insert one or several line below without changing current evil state
(defun spacemacs/evil-insert-line-below (count)
"Insert one of several lines below the current point's line without changing
the current state and point position."
(interactive "p")
(save-excursion
(evil-save-state (evil-open-below count))))
;; insert one or several line above without changing current evil state
(defun spacemacs/evil-insert-line-above (count)
"Insert one of several lines above the current point's line without changing
the current state and point position."
(interactive "p")
(save-excursion
(evil-save-state (evil-open-above count))))
(defun spacemacs/evil-goto-next-line-and-indent (&optional count)
(interactive "p")
(let ((counter (or count 1)))
(while (> counter 0)
(join-line 1)
(sp-newline)
(setq counter (1- counter)))))
;; from Prelude
;; TODO: dispatch these in the layers
(defvar spacemacs-indent-sensitive-modes
'(coffee-mode
python-mode
slim-mode
haml-mode
yaml-mode
makefile-mode
makefile-gmake-mode
makefile-imake-mode
makefile-bsdmake-mode)
"Modes for which auto-indenting is suppressed.")
(defcustom spacemacs-yank-indent-threshold 1000
"Threshold (# chars) over which indentation does not automatically occur."
:type 'number
:group 'spacemacs)
(defun spacemacs/indent-region-or-buffer ()
"Indent a region if selected, otherwise the whole buffer."
(interactive)
(unless (member major-mode spacemacs-indent-sensitive-modes)
(save-excursion
(if (region-active-p)
(progn
(indent-region (region-beginning) (region-end))
(message "Indented selected region."))
(progn
(evil-indent (point-min) (point-max))
(message "Indented buffer.")))
(whitespace-cleanup))))
;; idea from http://www.reddit.com/r/emacs/comments/312ge1/i_created_this_function_because_i_was_tired_of/
(defun spacemacs/eval-current-form ()
"Looks for the current def* or set* command then evaluates, unlike `eval-defun', does not go to topmost function"
(interactive)
(save-excursion
(search-backward-regexp "(def\\|(set")
(forward-list)
(call-interactively 'eval-last-sexp)))
;; from magnars
(defun spacemacs/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)))))
;; from https://gist.github.com/3402786
(defun spacemacs/toggle-maximize-buffer ()
"Maximize buffer"
(interactive)
(if (and (= 1 (length (window-list)))
(assoc'_ register-alist))
(jump-to-register '_)
(progn
(window-configuration-to-register '_)
(delete-other-windows))))
;; A small minor mode to use a big fringe
;; from http://bzg.fr/emacs-strip-tease.html
(defvar bzg-big-fringe-mode nil)
(define-minor-mode bzg-big-fringe-mode
"Minor mode to use big fringe in the current buffer."
:init-value nil
:global t
:variable bzg-big-fringe-mode
:group 'editing-basics
(if (not bzg-big-fringe-mode)
(set-fringe-style nil)
(set-fringe-mode
(/ (- (frame-pixel-width)
(* 100 (frame-char-width)))
2))))
(defun spacemacs/toggle-maximize-centered-buffer ()
"Maximize buffer and center it on the screen"
(interactive)
(if (= 1 (length (window-list)))
(progn (bzg-big-fringe-mode 0)
(jump-to-register '_))
(progn
(set-register '_ (list (current-window-configuration)))
(delete-other-windows)
(bzg-big-fringe-mode 1))))
(defun spacemacs/useless-buffer-p (buffer)
"Determines if a buffer is useful."
(let ((buf-paren-major-mode (get (with-current-buffer buffer
major-mode)
'derived-mode-parent))
(buf-name (buffer-name buffer)))
;; first find if useful buffer exists, if so returns nil and don't check for
;; useless buffers. If no useful buffer is found, check for useless buffers.
(unless (cl-loop for regexp in spacemacs-useful-buffers-regexp do
(when (or (eq buf-paren-major-mode 'comint-mode)
(string-match regexp buf-name))
(return t)))
(cl-loop for regexp in spacemacs-useless-buffers-regexp do
(when (string-match regexp buf-name)
(return t))))))
;; from magnars modified by ffevotte for dedicated windows support
(defun spacemacs/rotate-windows (count)
"Rotate your windows.
Dedicated windows are left untouched. Giving a negative prefix
argument takes the kindows rotate backwards."
(interactive "p")
(let* ((non-dedicated-windows (remove-if 'window-dedicated-p (window-list)))
(num-windows (length non-dedicated-windows))
(i 0)
(step (+ num-windows count)))
(cond ((not (> num-windows 1))
(message "You can't rotate a single window!"))
(t
(dotimes (counter (- num-windows 1))
(let* ((next-i (% (+ step i) num-windows))
(w1 (elt non-dedicated-windows i))
(w2 (elt non-dedicated-windows next-i))
(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)
(setq i next-i)))))))
(defun spacemacs/rotate-windows-backward (count)
"Rotate your windows backward."
(interactive "p")
(spacemacs/rotate-windows (* -1 count)))
(defun spacemacs/next-useful-buffer ()
"Switch to the next buffer and avoid special buffers."
(interactive)
(let ((start-buffer (current-buffer)))
(next-buffer)
(while (and (spacemacs/useless-buffer-p (current-buffer))
(not (eq (current-buffer) start-buffer)))
(next-buffer))))
(defun spacemacs/previous-useful-buffer ()
"Switch to the previous buffer and avoid special buffers."
(interactive)
(let ((start-buffer (current-buffer)))
(previous-buffer)
(while (and (spacemacs/useless-buffer-p (current-buffer))
(not (eq (current-buffer) start-buffer)))
(previous-buffer))))
;; from magnars
(defun spacemacs/rename-current-buffer-file ()
"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)))
(error "Buffer '%s' is not visiting a file!" name)
(let ((new-name (read-file-name "New name: " filename)))
(cond ((get-buffer new-name)
(error "A buffer named '%s' already exists!" new-name))
(t
(let ((dir (file-name-directory new-name)))
(when (and (not (file-exists-p dir)) (yes-or-no-p (format "Create directory '%s'?" dir)))
(make-directory dir t)))
(rename-file filename new-name 1)
(rename-buffer new-name)
(set-visited-file-name new-name)
(set-buffer-modified-p nil)
(message "File '%s' successfully renamed to '%s'" name (file-name-nondirectory new-name))))))))
;; from magnars
(defun spacemacs/delete-current-buffer-file ()
"Removes file connected to current buffer and kills buffer."
(interactive)
(let ((filename (buffer-file-name))
(buffer (current-buffer))
(name (buffer-name)))
(if (not (and filename (file-exists-p filename)))
(ido-kill-buffer)
(when (yes-or-no-p "Are you sure you want to delete this file? ")
(delete-file filename t)
(kill-buffer buffer)
(message "File '%s' successfully removed" filename)))))
;; from magnars
(defun spacemacs/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))))
;; found at http://emacswiki.org/emacs/KillingBuffers
(defun spacemacs/kill-other-buffers ()
"Kill all other buffers."
(interactive)
(let (name (buffer-name))
(when (yes-or-no-p (format "Killing all buffers except \"%s\" ? " buffer-file-name))
(mapc 'kill-buffer (delq (current-buffer) (buffer-list)))
(message "Buffers deleted!"))))
;; from http://dfan.org/blog/2009/02/19/emacs-dedicated-windows/
(defun spacemacs/toggle-current-window-dedication ()
"Toggle dedication state of a window."
(interactive)
(let* ((window (selected-window))
(dedicated (window-dedicated-p window)))
(set-window-dedicated-p window (not dedicated))
(message "Window %sdedicated to %s"
(if dedicated "no longer " "")
(buffer-name))))
;; http://camdez.com/blog/2013/11/14/emacs-show-buffer-file-name/
(defun spacemacs/show-and-copy-buffer-filename ()
"Show the full path to the current file in the minibuffer."
(interactive)
(let ((file-name (buffer-file-name)))
(if file-name
(progn
(message file-name)
(kill-new file-name))
(error "Buffer not visiting a file"))))
;; adapted from bozhidar
;; http://emacsredux.com/blog/2013/05/18/instant-access-to-init-dot-el/
(defun spacemacs/find-user-init-file ()
"Edit the `user-init-file', in the current window."
(interactive)
(find-file-existing user-init-file))
(defun spacemacs/find-dotfile ()
"Edit the `dotfile', in the current window."
(interactive)
(find-file-existing (dotspacemacs/location)))
(defun spacemacs/ediff-dotfile-and-template ()
"ediff the current `dotfile' with the template"
(interactive)
(ediff-files (dotspacemacs/location)
(concat dotspacemacs-template-directory ".spacemacs.template")))
(defun spacemacs/new-empty-buffer ()
"Create a new buffer called untitled(<n>)"
(interactive)
(let ((newbuf (generate-new-buffer-name "untitled")))
(switch-to-buffer newbuf)))
(defun spacemacs/home ()
"Go to home Spacemacs buffer"
(interactive)
(switch-to-buffer "*spacemacs*"))
(defun spacemacs/insert-line-above-no-indent (count)
(interactive "p")
(let ((p (+ (point) count)))
(save-excursion
(if (eq (line-number-at-pos) 1)
(evil-move-beginning-of-line)
(progn
(evil-previous-line)
(evil-move-end-of-line)))
(while (> count 0)
(insert "\n")
(setq count (1- count))))
(goto-char p)))
(defun spacemacs/insert-line-below-no-indent (count)
"Insert a new line below with no identation."
(interactive "p")
(save-excursion
(evil-move-end-of-line)
(while (> count 0)
(insert "\n")
(setq count (1- count)))))
;; from https://github.com/gempesaw/dotemacs/blob/emacs/dg-defun.el
(defun spacemacs/kill-matching-buffers-rudely (regexp &optional internal-too)
"Kill buffers whose name matches the specified REGEXP. This
function, unlike the built-in `kill-matching-buffers` does so
WITHOUT ASKING. The optional second argument indicates whether to
kill internal buffers too."
(interactive "sKill buffers matching this regular expression: \nP")
(dolist (buffer (buffer-list))
(let ((name (buffer-name buffer)))
(when (and name (not (string-equal name ""))
(or internal-too (/= (aref name 0) ?\s))
(string-match regexp name))
(kill-buffer buffer)))))
;; advise to prevent server from closing
(defvar spacemacs-really-kill-emacs nil
"prevent window manager close from closing instance.")
(defun spacemacs/persistent-server-running-p ()
"Requires spacemacs-really-kill-emacs to be toggled and
dotspacemacs-persistent-server to be t"
(and (fboundp 'server-running-p)
(server-running-p)
dotspacemacs-persistent-server))
(defadvice kill-emacs (around spacemacs-really-exit activate)
"Only kill emacs if a prefix is set"
(if (and (not spacemacs-really-kill-emacs)
(spacemacs/persistent-server-running-p))
(spacemacs/frame-killer)
ad-do-it))
(defadvice save-buffers-kill-emacs (around spacemacs-really-exit activate)
"Only kill emacs if a prefix is set"
(if (or spacemacs-really-kill-emacs (not dotspacemacs-persistent-server))
ad-do-it
(spacemacs/frame-killer)))
(defun spacemacs/save-buffers-kill-emacs ()
"Save all changed buffers and exit Spacemacs"
(interactive)
(setq spacemacs-really-kill-emacs t)
(save-buffers-kill-emacs))
(defun spacemacs/kill-emacs ()
"Lose all changes and exit Spacemacs"
(interactive)
(setq spacemacs-really-kill-emacs t)
(kill-emacs))
(defun spacemacs/prompt-kill-emacs ()
"Prompt to save changed buffers and exit Spacemacs"
(interactive)
(setq spacemacs-really-kill-emacs t)
(save-some-buffers)
(kill-emacs))
(defun spacemacs/frame-killer ()
"Kill server buffer and hide the main Emacs window"
(interactive)
(server-kill-buffer)
(condition-case nil
(delete-frame nil 1)
(error
(make-frame-invisible nil 1))))
(defun spacemacs/toggle-frame-fullscreen ()
"Respect the `dotspacemacs-fullscreen-use-non-native' variable when
toggling fullscreen."
(interactive)
(if dotspacemacs-fullscreen-use-non-native
(spacemacs/toggle-frame-fullscreen-non-native)
(toggle-frame-fullscreen)))
(defun spacemacs/toggle-fullscreen ()
"Toggle full screen on X11 and Carbon"
(interactive)
(cond
((eq window-system 'x)
(set-frame-parameter nil 'fullscreen
(when (not (frame-parameter nil 'fullscreen))
'fullboth)))
((eq window-system 'mac)
(set-frame-parameter
nil 'fullscreen
(when (not (frame-parameter nil 'fullscreen)) 'fullscreen)))))
(defun spacemacs/toggle-frame-fullscreen-non-native ()
"Toggle full screen non-natively. Uses the `fullboth' frame paramerter
rather than `fullscreen'. Useful to fullscreen on OSX w/o animations."
(interactive)
(modify-frame-parameters
nil
`((maximized
. ,(unless (memq (frame-parameter nil 'fullscreen) '(fullscreen fullboth))
(frame-parameter nil 'fullscreen)))
(fullscreen
. ,(if (memq (frame-parameter nil 'fullscreen) '(fullscreen fullboth))
(if (eq (frame-parameter nil 'maximized) 'maximized)
'maximized)
'fullboth)))))
;; taken from Prelude: https://github.com/bbatsov/prelude
(defmacro spacemacs|advise-commands (advice-name commands class &rest body)
"Apply advice named ADVICE-NAME to multiple COMMANDS.
The body of the advice is in BODY."
`(progn
,@(mapcar (lambda (command)
`(defadvice ,command
(,class ,(intern (format "%S-%s" command advice-name))
activate)
,@body))
commands)))
(defun spacemacs/safe-revert-buffer ()
"Prompt before reverting the file."
(interactive)
(revert-buffer nil nil))
(defun spacemacs/safe-erase-buffer ()
"Prompt before erasing the content of the file."
(interactive)
(if (y-or-n-p (format "Erase content of buffer %s ? " (current-buffer)))
(erase-buffer)))
(defun spacemacs/ert-run-tests-buffer ()
"Run all the tests in the current buffer."
(interactive)
(save-buffer)
(load-file (buffer-file-name))
(ert t))
(defun spacemacs/alternate-buffer ()
"Switch back and forth between current and last buffer in the
current window."
(interactive)
(if (evil-alternate-buffer)
(switch-to-buffer (car (evil-alternate-buffer)))
(switch-to-buffer (other-buffer (current-buffer) t))))
(defun spacemacs/highlight-TODO-words ()
"Highlight keywords for "
(interactive)
(font-lock-add-keywords
nil '(("\\<\\(\\(FIX\\(ME\\)?\\|TODO\\|OPTIMIZE\\|HACK\\|REFACTOR\\):\\)"
1 font-lock-warning-face t))))
(defun current-line ()
"Return the line at point as a string."
(buffer-substring (line-beginning-position) (line-end-position)))
(defun spacemacs/open-in-external-app ()
"Open current file in external application."
(interactive)
(let ((file-path (if (eq major-mode 'dired-mode)
(dired-get-file-for-visit)
(buffer-file-name))))
(if file-path
(cond
((spacemacs/system-is-mswindows) (w32-shell-execute "open" (replace-regexp-in-string "/" "\\\\" file-path)))
((spacemacs/system-is-mac) (shell-command (format "open \"%s\"" file-path)))
((spacemacs/system-is-linux) (let ((process-connection-type nil))
(start-process "" nil "xdg-open" file-path))))
(message "No file associated to this buffer."))))
(defun spacemacs/next-error (&optional n reset)
"Dispatch to flycheck or standard emacs error."
(interactive "P")
(if (and (boundp 'flycheck-mode)
(symbol-value flycheck-mode))
(call-interactively 'flycheck-next-error)
(call-interactively 'next-error)))
(defun spacemacs/previous-error (&optional n reset)
"Dispatch to flycheck or standard emacs error."
(interactive "P")
(if (and (boundp 'flycheck-mode)
(symbol-value flycheck-mode))
(call-interactively 'flycheck-previous-error)
(call-interactively 'previous-error)))
(defun spacemacs/switch-to-minibuffer-window ()
"switch to minibuffer window (if active)"
(interactive)
(when (active-minibuffer-window)
(select-window (active-minibuffer-window))))
(defun spacemacs/comint-clear-buffer ()
(interactive)
(let ((comint-buffer-maximum-size 0))
(comint-truncate-buffer)))
;; http://stackoverflow.com/a/10216338/4869
(defun spacemacs/copy-whole-buffer-to-clipboard ()
"Copy entire buffer to clipboard"
(interactive)
(clipboard-kill-ring-save (point-min) (point-max)))
(defun spacemacs/copy-clipboard-to-whole-buffer ()
"Copy clipboard and replace buffer"
(interactive)
(delete-region (point-min) (point-max))
(clipboard-yank)
(deactivate-mark))
;; hide mode line
;; from http://bzg.fr/emacs-hide-mode-line.html
(defvar-local hidden-mode-line-mode nil)
(define-minor-mode hidden-mode-line-mode
"Minor mode to hide the mode-line in the current buffer."
:init-value nil
:global t
:variable hidden-mode-line-mode
:group 'editing-basics
(if hidden-mode-line-mode
(setq hide-mode-line mode-line-format
mode-line-format nil)
(setq mode-line-format hide-mode-line
hide-mode-line nil))
(force-mode-line-update)
;; Apparently force-mode-line-update is not always enough to
;; redisplay the mode-line
(redraw-display)
(when (and (called-interactively-p 'interactive)
hidden-mode-line-mode)
(run-with-idle-timer
0 nil 'message
(concat "Hidden Mode Line Mode enabled. "
"Use M-x hidden-mode-line-mode to make the mode-line appear."))))
;; BEGIN align functions
;; modified function from http://emacswiki.org/emacs/AlignCommands
(defun spacemacs/align-repeat (start end regexp &optional justify-right after)
"Repeat alignment with respect to the given regular expression.
If JUSTIFY-RIGHT is non nil justify to the right instead of the
left. If AFTER is non-nil, add whitespace to the left instead of
the right."
(interactive "r\nsAlign regexp: ")
(let ((complete-regexp (if after
(concat regexp "\\([ \t]*\\)")
(concat "\\([ \t]*\\)" regexp)))
(group (if justify-right -1 1)))
(align-regexp start end complete-regexp group 1 t)))
;; Modified answer from http://emacs.stackexchange.com/questions/47/align-vertical-columns-of-numbers-on-the-decimal-point
(defun spacemacs/align-repeat-decimal (start end)
"Align a table of numbers on decimal points and dollar signs (both optional)"
(interactive "r")
(require 'align)
(align-region start end nil
'((nil (regexp . "\\([\t ]*\\)\\$?\\([\t ]+[0-9]+\\)\\.?")
(repeat . t)
(group 1 2)
(spacing 1 1)
(justify nil t)))
nil))
(defmacro spacemacs|create-align-repeat-x (name regexp &optional justify-right default-after)
(let ((new-func (intern (concat "spacemacs/align-repeat-" name))))
`(defun ,new-func (start end switch)
(interactive "r\nP")
(let ((after (not (eq (if switch t nil) (if ,default-after t nil)))))
(spacemacs/align-repeat start end ,regexp ,justify-right after)))))
(spacemacs|create-align-repeat-x "comma" "," nil t)
(spacemacs|create-align-repeat-x "semicolon" ";" nil t)
(spacemacs|create-align-repeat-x "colon" ":" nil t)
(spacemacs|create-align-repeat-x "equal" "=")
(spacemacs|create-align-repeat-x "math-oper" "[+\\-*/]")
(spacemacs|create-align-repeat-x "ampersand" "&")
(spacemacs|create-align-repeat-x "bar" "|")
(spacemacs|create-align-repeat-x "left-paren" "(")
(spacemacs|create-align-repeat-x "right-paren" ")" t)
;; END align functions
(defun spacemacs/write-file ()
"Write the file if visiting a file.
Otherwise ask for new filename."
(interactive)
(if (buffer-file-name)
(call-interactively 'evil-write)
(call-interactively 'write-file)))
(defun spacemacs/dos2unix ()
"Converts the current buffer to UNIX file format."
(interactive)
(set-buffer-file-coding-system 'undecided-unix nil))
(defun spacemacs/unix2dos ()
"Converts the current buffer to DOS file format."
(interactive)
(set-buffer-file-coding-system 'undecided-dos nil))
(defun spacemacs/copy-file ()
"Write the file under new name."
(interactive)
(call-interactively 'write-file))
(defun spacemacs//imagep (object)
"Tests whether the given object is an image (a list whose
first element is the symbol `image')."
(and (listp object)
object
(eq 'image (car object))))
(defun spacemacs/uniquify-lines ()
"Remove duplicate adjacent lines in region or current buffer"
(interactive)
(save-excursion
(save-restriction
(let ((beg (if (region-active-p) (region-beginning) (point-min)))
(end (if (region-active-p) (region-end) (point-max))))
(goto-char beg)
(while (re-search-forward "^\\(.*\n\\)\\1+" end t)
(replace-match "\\1"))))))
(defun spacemacs/sort-lines ()
"Sort lines in region or current buffer"
(interactive)
(let ((beg (if (region-active-p) (region-beginning) (point-min)))
(end (if (region-active-p) (region-end) (point-max))))
(sort-lines nil beg end)))
;; BEGIN linum mouse helpers
(defvar spacemacs-linum-mdown-line nil
"Define persistent variable for linum selection")
(defun spacemacs/line-at-click ()
"Determine the visual line at click"
(save-excursion
(let ((click-y (cddr (mouse-position)))
(debug-on-error t)
(line-move-visual t))
(goto-char (window-start))
(next-line (1- click-y))
(1+ (line-number-at-pos))
)))
(defun spacemacs/md-select-linum (event)
"Set point as spacemacs-linum-mdown-line"
(interactive "e")
(mouse-select-window event)
(goto-line (spacemacs/line-at-click))
(set-mark (point))
(setq spacemacs-linum-mdown-line
(line-number-at-pos)))
(defun spacemacs/mu-select-linum ()
"Select code block between point and spacemacs-linum-mdown-line"
(interactive)
(when spacemacs-linum-mdown-line
(let (mu-line)
(setq mu-line (spacemacs/line-at-click))
(goto-line (max spacemacs-linum-mdown-line mu-line))
(set-mark (line-end-position))
(goto-line (min spacemacs-linum-mdown-line mu-line))
(setq spacemacs-linum-mdown-line nil))))
(defun spacemacs/select-current-block ()
"Select the current block of text between blank lines."
(interactive)
(let (p1 p2)
(progn
(if (re-search-backward "\n[ \t]*\n" nil "move")
(progn (re-search-forward "\n[ \t]*\n")
(setq p1 (point)))
(setq p1 (point)))
(if (re-search-forward "\n[ \t]*\n" nil "move")
(progn (re-search-backward "\n[ \t]*\n")
(setq p2 (point)))
(setq p2 (point))))
(set-mark p1)))
;; END linum mouse helpers
;; From http://xugx2007.blogspot.ca/2007/06/benjamin-rutts-emacs-c-development-tips.html
(setq compilation-finish-function
(lambda (buf str)
(if (or (string-match "exited abnormally" str)
(string-match "FAILED" (buffer-string)))
;; there were errors
(message "There were errors. SPC-e-n to visit.")
(unless (or (string-match "Grep finished" (buffer-string))
(string-match "Ag finished" (buffer-string))
(string-match "nosetests" (buffer-name)))
;; no errors
(message "compilation ok.")))))
;; from http://www.emacswiki.org/emacs/WordCount
(defun spacemacs/count-words-analysis (start end)
"Count how many times each word is used in the region.
Punctuation is ignored."
(interactive "r")
(let (words)
(save-excursion
(goto-char start)
(while (re-search-forward "\\w+" end t)
(let* ((word (intern (match-string 0)))
(cell (assq word words)))
(if cell
(setcdr cell (1+ (cdr cell)))
(setq words (cons (cons word 1) words))))))
(when (interactive-p)
(message "%S" words))
words))
;; byte compile elisp files
(defun byte-compile-current-buffer ()
"`byte-compile' current buffer if it's emacs-lisp-mode and compiled file exists."
(interactive)
(when (and (eq major-mode 'emacs-lisp-mode)
(file-exists-p (byte-compile-dest-file buffer-file-name)))
(byte-compile-file buffer-file-name)))
(add-hook 'after-save-hook 'byte-compile-current-buffer)
;; indent on paste
;; from Prelude: https://github.com/bbatsov/prelude
(defun spacemacs/yank-advised-indent-function (beg end)
"Do indentation, as long as the region isn't too large."
(if (<= (- end beg) spacemacs-yank-indent-threshold)
(indent-region beg end nil)))
(spacemacs|advise-commands
"indent" (yank yank-pop evil-paste-before evil-paste-after) after
"If current mode is not one of spacemacs-indent-sensitive-modes
indent yanked text (with universal arg don't indent)."
(if (and (not (equal '(4) (ad-get-arg 0)))
(not (member major-mode spacemacs-indent-sensitive-modes))
(or (derived-mode-p 'prog-mode)
(member major-mode spacemacs-indent-sensitive-modes)))
(let ((transient-mark-mode nil))
(spacemacs/yank-advised-indent-function (region-beginning) (region-end)))))
(defun spacemacs//intersperse (seq separator)
"Returns a list with `SEPARATOR' added between each element
of the list `SEQ'."
(cond
((not seq) nil)
((not (cdr seq)) seq)
(t (append (list (car seq) separator)
(spacemacs//intersperse (cdr seq) separator)))))
(defun spacemacs//mode-line-nonempty (seg)
"Checks whether a modeline segment (classical Emacs style)
is nonempty."
(let ((val (format-mode-line seg)))
(cond ((listp val) val)
((stringp val) (< 0 (length val)))
(t))))