Starter Kit Defuns

This is part of the Emacs Starter Kit.

Starter Kit Defuns

The starter-kit-coding-hook

A single hook holding those functions which should be run in every code buffer.

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 sk-smartparens ()
  (turn-on-smartparens-mode))

(defun sk-local-comment-auto-fill ()
  (set (make-local-variable 'comment-auto-fill-only-comments) t)
  (auto-fill-mode t))

(defun sk-pretty-lambdas ()
  (font-lock-add-keywords
   nil `(("(?\\(lambda\\>\\)"
          (0 (progn (compose-region (match-beginning 1) (match-end 1)
                                    ,(make-char 'greek-iso8859-7 107))
                    nil))))))

(defun sk-add-watchwords ()
  (font-lock-add-keywords
   nil '(("\\<\\(FIX\\(ME\\)?\\|TODO\\|HACK\\|REFACTOR\\|NOCOMMIT\\)"
          1 font-lock-warning-face t))))

(defun sk-indent-or-complete ()
  "Complete if point is at end of a word, otherwise indent line."
  (interactive)
  (if (looking-at "\\>")
      (hippie-expand nil)
    (indent-for-tab-command)))

(defun sk-hide-show-mode ()
  (local-set-key (kbd "<s-right>") 'hs-show-block)
  (local-set-key (kbd "<s-left>")  'hs-hide-block)
  (local-set-key (kbd "<s-up>")    'hs-hide-all)
  (local-set-key (kbd "<s-down>")  'hs-show-all)
  (hs-minor-mode   t)
  )

Perform a bunch of safe operations on the whitespace content of a buffer. Does not indent buffer, because it is used for a before-save-hook, and that might be bad.

(defun sk-cleanup-buffer-safe ()
  (interactive)
  ;;(untabify (point-min) (point-max))
  (delete-trailing-whitespace))

Perform a bunch of operations on the whitespace content of a buffer. Including indent-buffer, which should not be called automatically on save.

(defun sk-cleanup-buffer ()
  (interactive)
  (starter-kit-cleanup-buffer-safe)
  (indent-region (point-min) (point-max)))

Handling buffers

Rename/Move both current buffer and file currently visited

From Steve Yegge .emacs

(defun sk-rename-file-and-buffer (new-name)
  "Renames both current buffer and file it's visiting to NEW-NAME."
  (interactive "sNew name: ")
  (let ((name (buffer-name))
        (filename (buffer-file-name)))
    (if (not filename)
        (message "Buffer '%s' is not visiting a file!" name)
      (if (get-buffer new-name)
          (message "A buffer named '%s' already exists!" new-name)
        (progn
          (rename-file name new-name 1)
          (rename-buffer new-name)
          (set-visited-file-name new-name)
          (set-buffer-modified-p nil))))))

(defun sk-move-buffer-file (dir)
  "Moves both current buffer and file it's visiting to DIR."
  (interactive "DNew directory: ")
  (let* ((name (buffer-name))
         (filename (buffer-file-name))
         (dir
          (if (string-match dir "\\(?:/\\|\\\\)$")
              (substring dir 0 -1) dir))
         (newname (concat dir "/" name)))

    (if (not filename)
        (message "Buffer '%s' is not visiting a file!" name)
      (progn (copy-file filename newname 1)
             (delete-file filename)
             (set-visited-file-name newname)
             (set-buffer-modified-p nil) t))))

Delete current buffer file

From Magnars blog

(defun sk-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 remove this file? ")
        (delete-file filename)
        (kill-buffer buffer)
        (message "File '%s' successfully removed" filename)))))

Stop displaying minibuffer when mouse go to another buffer

(defun sk-stop-using-minibuffer ()
  "Kill the minibuffer"
  (when (and (>= (recursion-depth) 1) (active-minibuffer-window))
    (abort-recursive-edit)))

Touching the current buffer

(defun sk-touch ()
  (interactive)
  (shell-command (concat "touch " (shell-quote-argument (buffer-file-name)))))

Splitting buffer

When splitting is done, emacs will open the next buffer

(defadvice split-window-vertically
  (after my-window-splitting-advice first () activate)
  (set-window-buffer (next-window) (other-buffer)))
(defadvice split-window-horizontally
  (after my-window-splitting-advice first () activate)
  (set-window-buffer (next-window) (other-buffer)))

Handling window

From Magnars blog

(defun sk-toggle-window-split ()
  (interactive)
  (if (= (count-windows) 2)
      (let* ((this-win-buffer (window-buffer))
             (next-win-buffer (window-buffer (next-window)))
             (this-win-edges (window-edges (selected-window)))
             (next-win-edges (window-edges (next-window)))
             (this-win-2nd (not (and (<= (car this-win-edges)
                                         (car next-win-edges))
                                     (<= (cadr this-win-edges)
                                         (cadr next-win-edges)))))
             (splitter
              (if (= (car this-win-edges)
                     (car (window-edges (next-window))))
                  'split-window-horizontally
                'split-window-vertically)))
        (delete-other-windows)
        (let ((first-win (selected-window)))
          (funcall splitter)
          (if this-win-2nd (other-window 1))
          (set-window-buffer (selected-window) this-win-buffer)
          (set-window-buffer (next-window) next-win-buffer)
          (select-window first-win)
          (if this-win-2nd (other-window 1))))))

Saving desktop status

(defun sk-desktop ()
  "Load the desktop and enable autosaving"
  (interactive)
  (let ((desktop-load-locked-desktop "ask"))
    (desktop-read)
    (desktop-save-mode 1)))

(defun sk-desktop-save ()
  (interactive)
  (desktop-save desktop-dirname))

Misc.

Edit current buffer with sudo rights

(defun sk-sudo-edit-current-file (&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))))

Grepping words

For sure there might be a better way and tool to do that but I am used to use it

(defun sk-grep ()
  "grep the whole directory for something defaults to term at cursor position"
  (interactive)
  (setq default (thing-at-point 'symbol))
  (setq needle (or (read-string (concat "grep for <" default "> ")) default))
  (setq needle (if (equal needle "") default needle))
  (grep (concat "egrep -s -i -n -r " needle " *")))

Try to use also ack-and-a-half and create shorter aliases

(defalias 'ack 'ack-and-a-half)
(defalias 'ack-same 'ack-and-a-half-same)
(defalias 'ack-find-file 'ack-and-a-half-find-file)
(defalias 'ack-find-file-same 'ack-and-a-half-find-file-same)
(setq ack-and-a-half-use-ido t)

Toggling fullscreen

(defun sk-toggle-fullscreen ()
  (interactive)
  (set-frame-parameter nil 'fullscreen (if (frame-parameter nil 'fullscreen)
                                           nil
                                           'fullboth)))

Sending libnotify popup

(defun sk-popup (title msg)
  "Show a popup if we're on X, or echo it otherwise; TITLE is the
title of the message, MSG is the context."
  (if (eq window-system 'x)
      (shell-command (concat "notify-send -t 2000 -i emacs"
                             " '" title "' '" msg "'"))
    ;; text only version
    (message (concat title ": " msg))))
(defun sk-test-popup ()
  (interactive)
  (sk-popup "Test Notification :" "test"))

Googling active region

From Emacs redux.

(defun sk-google ()
  "Google the selected region if any, display a query prompt otherwise."
  (interactive)
  (browse-url
   (concat
    "http://www.google.com/search?ie=utf-8&oe=utf-8&q="
    (url-hexify-string (if mark-active
                           (buffer-substring (region-beginning) (region-end))
                         (read-string "Google: "))))))
(global-set-key (kbd "s-g") 'sk-google)

Hooks

Coding

(add-hook 'starter-kit-coding-hook 'sk-local-comment-auto-fill)
(add-hook 'starter-kit-coding-hook 'sk-pretty-lambdas)
(add-hook 'starter-kit-coding-hook 'sk-smartparens)
(add-hook 'starter-kit-coding-hook 'sk-add-watchwords)
(add-hook 'starter-kit-coding-hook 'sk-hide-show-mode)
(add-hook 'starter-kit-coding-hook 'idle-highlight-mode)
(add-hook 'starter-kit-coding-hook 'wrap-region-mode)
(add-hook 'starter-kit-coding-hook 'linum-mode)
(add-hook 'starter-kit-coding-hook 'turn-on-fci-mode)
(defun run-starter-kit-coding-hook ()
  "Enable things that are convenient across all coding buffers."
  (run-hooks 'starter-kit-coding-hook))

Indent correctly pasted code

(defadvice yank (after indent-region activate)
(if (member major-mode '(emacs-lisp-mode scheme-mode lisp-mode
                                         c-mode c++-mode objc-mode
                                         latex-mode plain-tex-mode
                                         python-mode org-mode))
    (indent-region (region-beginning) (region-end) nil)))

Clean up buffer before saving

(add-hook 'before-save-hook 'sk-cleanup-buffer-safe)

Store session before saving

(add-hook 'auto-save-hook 'sk-desktop-save)

Create a directory when there is not

(add-hook 'before-save-hook
          (lambda ()
            (let ((dir (file-name-directory buffer-file-name)))
              (when (and (not (file-exists-p dir))
                         (y-or-n-p (format "Directory %s does not exist. Create it?" dir)))
                (make-directory dir t)))))

Misc.

(add-hook 'mouse-leave-buffer-hook 'sk-stop-using-minibuffer)
(add-hook 'text-mode-hook 'turn-on-auto-fill)
File under version control - commit 135971e - 2014-11-29