;; sneakin.el - Functions and commands to make emacs more handy ;; Copyright 2004 Nolan Eakins ;; 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 2 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 this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA (require 'format-spec) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; The following commands are added and bound to ;; a key sequence: ;; Key Command ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; sneakin-customize ;; C-c C-c sneakin-insert-c++-class ;; C-c M-c sneakin-insert-c++-prefix ;; C-c C sneakin-insert-c++-destructor ;; C-c c sneakin-insert-c++-constructor ;; C-c C-d sneakin-insert-c-ifndef-define ;; C-c d sneakin-insert-c-header-define ;; C-c h sneakin-insert-c-file-header ;; C-c C-i sneakin-insert-c-system-include ;; C-c i sneakin-insert-c-local-include ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; Customization variables ;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defgroup sneakin nil "Options for Sneakin's helpers" :group 'emacs) (defcustom sneakin-c++-class-template "class %n%c { public: %n(); ~%n(); private: };" "The template to use for new classes. The fields available are: %n Class name %c Where to move the cursor" :type 'string :group 'sneakin) (defcustom sneakin-c-local-include-template "#include \"%c\"" "Template for local includes. The fields available are: %c Position of cursor" :type 'string :group 'sneakin) (defcustom sneakin-c-system-include-template "#include <%c>" "Template for system includes. The fields available are: %c Position of cursor" :type 'string :group 'sneakin) (defcustom sneakin-c-ifndef-define-template "#ifndef %d #define %d %c #endif /* %d */" "Template used for adding #ifndef #define pairs. The fields available are: %d Name of the definition %c Position to move cursor to" :type 'string :group 'sneakin) (defcustom sneakin-c++-class-constructor-template "%n::%n(%c) { }" "Template used for defining constructors. The available fields are: %n Class name %c Position to move cursor to" :type 'string :group 'sneakin) (defcustom sneakin-c++-class-destructor-template "%n::~%n() { %c }" "Template used for defining destructors. The available fields are: %n Class name %c Position to move cursor to" :type 'string :group 'sneakin) (defcustom sneakin-c++-prefix-template "%n::%c()" "Template used for inserting method prefixes. The available fields are: %n Class name %c Position to move the cursor too" :type 'string :group 'sneakin) (defcustom sneakin-c-file-header-template "/* * %f - %c * Copyright (c) 2004 %a <%e> * * 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 2 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 this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */" "File header comment. The available fields are: %a Author's real name (obtained from user-full-name) %e Email address (obtained from user-mail-address) %f Filename %c Cursor position" :type 'string :group 'sneakin) ;;;;;;;;;;;;;;;;;;;;;;; ;; The Actual Helpers ;;;;;;;;;;;;;;;;;;;;;;; (defun sneakin-customize () "customize sneakin's helpers" (interactive) (customize-group 'sneakin)) (defun sneakin-concat-symbols (a b) "Concatenate two symbols" (intern (concat (symbol-name a) (symbol-name b)))) (defun sneakin-num-lines (str) "Returns the number of lines in STR" (length (split-string str "\n"))) (defun sneakin-match-line (regexp input &optional counter) "Goes through either a list of lines or a string that gets split up into lines, INPUT, looking for REGEXP. When REGEXP is matched, a pair (line . posisition) is returned. If REGEXP is not found, nil is returned. COUNTER is used internally." (if (not input) nil (let* ((lines (if (stringp input) (split-string input "\n") input)) (line (car lines)) (match (string-match regexp line)) (counter (if counter counter 0))) (if (not match) (sneakin-match-line regexp (cdr lines) (+ counter 1)) (cons counter match))))) (defun sneakin-template-move-cursor (template &optional init-line-offset) (let ((pos (sneakin-match-line "%c" template))) (if pos (let ((line (car pos)) (col (cdr pos))) (if line (previous-line (- (sneakin-num-lines template) line 1))) (move-to-column (if (= line 0) (+ col init-line-offset) col)))))) (defun sneakin-insert-template (template specs &optional move-cursor) (let ((str (format-spec template (append specs (list (cons ?c "%c"))))) (end-pos (current-column))) (insert (format-spec str (list (cons ?c "")))) (if move-cursor (sneakin-template-move-cursor str end-pos)))) (defun sneakin-insert-c-ifndef-define (define &optional move-cursor) "Inserts an #ifdef #define pair" (interactive (list (read-string "Define? ") t)) (if (not (eq define nil)) (sneakin-insert-template sneakin-c-ifndef-define-template (list (cons ?d define)) move-cursor))) (defun sneakin-insert-c-header-define (&optional move-cursor) "Creates an #ifdef #define pair for a header file. The buffer's filename is used for the define." (interactive (list t)) (let* ((filename (buffer-file-name)) (def (replace-regexp-in-string "\\." "_" (upcase (file-name-nondirectory filename))))) (sneakin-insert-c-ifndef-define def move-cursor))) (defun sneakin-insert-c-include (template &optional move-cursor) (sneakin-insert-template template nil move-cursor)) (defun sneakin-insert-c-system-include (&optional move-cursor) "Inserts an '#include <>'" (interactive (list t)) (sneakin-insert-c-include sneakin-c-system-include-template move-cursor)) (defun sneakin-insert-c-local-include (&optional move-cursor) "Inserts an '#include \"\"'" (interactive (list t)) (sneakin-insert-c-include sneakin-c-local-include-template move-cursor)) (defun sneakin-insert-c++-structor (template class &optional move-cursor) (sneakin-insert-template template (list (cons ?n class)) move-cursor)) (defun sneakin-insert-c++-constructor (class &optional move-cursor) "Inserts a barebones definition of a constructor" (interactive (list (read-string "Class: ") t)) (sneakin-insert-c++-structor sneakin-c++-class-constructor-template class move-cursor)) (defun sneakin-insert-c++-destructor (class &optional move-cursor) "Inserts a barebones definition of a destructor" (interactive (list (read-string "Class: ") t)) (sneakin-insert-c++-structor sneakin-c++-class-destructor-template class move-cursor)) (defun sneakin-insert-c++-class (class &optional move-cursor) "Inserts a class declaration" (interactive (list (read-string "Class: ") t)) (sneakin-insert-template sneakin-c++-class-template (list (cons ?n class)) move-cursor)) (defun sneakin-insert-c++-prefix (class &optional move-cursor) "Typically inserts a CLASS::" (interactive (list (read-string "Class: ") t)) (sneakin-insert-template sneakin-c++-prefix-template (list (cons ?n class)) move-cursor)) (defun sneakin-insert-c-file-header (&optional filename move-cursor) "Inserts a standard file header comment. The default is the GPL." (interactive (list (file-name-nondirectory (buffer-file-name)) t)) (sneakin-insert-template sneakin-c-file-header-template (list (cons ?f filename) (cons ?a user-full-name) (cons ?e user-mail-address)) move-cursor)) (defun sneakin-add-c-key-hooks (modes) "Goes through MODES adding a mode hook to define keys for the above functions. MODES is a list of modes." (if modes (let* ((mode (car modes)) (hook (sneakin-concat-symbols mode '-hook)) (map (sneakin-concat-symbols mode '-map))) (add-hook hook `(lambda () (define-key ,map "\C-cd" 'sneakin-insert-c-header-define) (define-key ,map "\C-c\C-d" 'sneakin-insert-c-ifndef-define) (define-key ,map "\C-c\C-i" 'sneakin-insert-c-system-include) (define-key ,map "\C-ci" 'sneakin-insert-c-local-include) (define-key ,map "\C-c+" 'c++-mode) (define-key ,map "\C-c-" 'c-mode) (define-key ,map "\C-cc" 'sneakin-insert-c++-constructor) (define-key ,map "\C-cC" 'sneakin-insert-c++-destructor) (define-key ,map "\C-c\C-c" 'sneakin-insert-c++-class) (define-key ,map "\C-c\M-c" 'sneakin-insert-c++-prefix) (define-key ,map "\C-ch" 'sneakin-insert-c-file-header))) (sneakin-add-c-key-hooks (cdr modes))))) (sneakin-add-c-key-hooks '(c-mode c++-mode)) ;; Speak functions (defvar *flite* (start-process "flite" nil "flite")) (defun sneakin-speak-start-flite () (if (eq (process-status *flite*) 'exit) (setq *flite* (start-process "flite" nil "flite" "-l")))) (defun sneakin-speak-string (str) (interactive (list (read-string "Say what? "))) (sneakin-speak-start-flite) (process-send-string *flite* str) (process-send-string *flite* "\n") (process-send-eof *flite*) t) (defun sneakin-speak-region (start end) (interactive "r") (sneakin-speak-start-flite) (process-send-region *flite* start end) (process-send-string *flite* "\n") (process-send-eof *flite*) t) (defun sneakin-speak-line () (interactive) (sneakin-speak-region (line-beginning-position) (line-end-position))) (add-hook 'kill-emacs-hook (lambda () (process-kill-without-query *flite*))) (provide 'sneakin)