ad0f26abde
This is needed to get the frame to properly close when running a client from the terminal. server-kill-buffer will close the frame for the terminal only if the terminal was opened with a file argument and you haven't changed buffers. make-frame-invisible is still needed as a fall back if you are still working from the first emacs window since it won't let you delete the last frame.
913 lines
32 KiB
EmacsLisp
913 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))))
|
|
|
|
(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/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))))
|