;;; guile-c.el --- Guile C editing commands ;; Copyright (C) 2001, 2006 Free Software Foundation, Inc. ;;;; This library is free software; you can redistribute it and/or ;;;; modify it under the terms of the GNU Lesser General Public ;;;; License as published by the Free Software Foundation; either ;;;; version 3 of the License, or (at your option) any later version. ;;;; ;;;; This library 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 ;;;; Lesser General Public License for more details. ;;;; ;;;; You should have received a copy of the GNU Lesser General Public ;;;; License along with this library; if not, write to the Free ;;;; Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA ;;;; 02111-1307 USA ;;; Commentary: ;; (add-hook 'c-mode-hook ;; (lambda () ;; (require 'guile-c) ;; (define-key c-mode-map "\C-c\C-g\C-p" 'guile-c-insert-define) ;; (define-key c-mode-map "\C-c\C-g\C-e" 'guile-c-edit-docstring) ;; (define-key c-mode-map "\C-c\C-g\C-d" 'guile-c-deprecate-region) ;; )) ;;; Code: (require 'cc-mode) (defvar guile-c-prefix "scm_") ;;; ;;; Insert templates ;;; (defun guile-c-insert-define () "Insert a template of a Scheme procedure. M-x guile-c-insert-define RET foo arg , opt . rest => SCM_DEFINE (scm_foo, \"foo\", 1, 1, 1, (SCM arg, SCM opt, SCM rest), \"\") #define FUNC_NAME s_scm_foo { } #undef FUNC_NAME" (interactive) (let ((tokens (split-string (read-string "Procedure: "))) name args opts rest) ;; Get procedure name (if (not tokens) (error "No procedure name")) (setq name (car tokens) tokens (cdr tokens)) ;; Get requisite arguments (while (and tokens (not (member (car tokens) '("," ".")))) (setq args (cons (car tokens) args) tokens (cdr tokens))) (setq args (nreverse args)) ;; Get optional arguments (when (string= (car tokens) ",") (setq tokens (cdr tokens)) (while (and tokens (not (string= (car tokens) "."))) (setq opts (cons (car tokens) opts) tokens (cdr tokens))) (setq opts (nreverse opts))) ;; Get rest argument (when (string= (car tokens) ".") (setq rest (list (cadr tokens)))) ;; Insert template (let ((c-name (guile-c-name-from-scheme-name name))) (insert (format "SCM_DEFINE (%s, \"%s\", %d, %d, %d,\n" c-name name (length args) (length opts) (length rest)) "\t (" (mapconcat (lambda (a) (concat "SCM " a)) (append args opts rest) ", ") "),\n" "\t \"\")\n" "#define FUNC_NAME s_" c-name "\n" "{\n\n}\n" "#undef FUNC_NAME\n\n") (previous-line 4) (indent-for-tab-command)))) (defun guile-c-name-from-scheme-name (name) (while (string-match "\\?$" name) (setq name (replace-match "_p" t t name))) (while (string-match "!$" name) (setq name (replace-match "_x" t t name))) (while (string-match "^%" name) (setq name (replace-match "sys_" t t name))) (while (string-match "->" name) (setq name (replace-match "_to_" t t name))) (while (string-match "[-:]" name) (setq name (replace-match "_" t t name))) (concat guile-c-prefix name)) ;;; ;;; Edit docstrings ;;; (defvar guile-c-window-configuration nil) (defun guile-c-edit-docstring () (interactive) (let* ((region (guile-c-find-docstring)) (doc (if region (buffer-substring (car region) (cdr region))))) (if (not doc) (error "No docstring!") (setq guile-c-window-configuration (current-window-configuration)) (with-current-buffer (get-buffer-create "*Guile Docstring*") (erase-buffer) (insert doc) (goto-char (point-min)) (while (not (eobp)) (if (looking-at "[ \t]*\"") (delete-region (match-beginning 0) (match-end 0))) (end-of-line) (if (eq (char-before (point)) ?\") (delete-backward-char 1)) (if (and (eq (char-before (point)) ?n) (eq (char-before (1- (point))) ?\\)) (delete-backward-char 2)) (forward-line)) (goto-char (point-min)) (texinfo-mode) (if global-font-lock-mode (font-lock-fontify-buffer)) (local-set-key "\C-c\C-c" 'guile-c-edit-finish) (setq fill-column 63) (switch-to-buffer-other-window (current-buffer)) (message "Type `C-c C-c' to finish"))))) (defun guile-c-edit-finish () (interactive) (goto-char (point-max)) (while (eq (char-before) ?\n) (backward-delete-char 1)) (goto-char (point-min)) (if (eobp) (insert "\"\"") (while (not (eobp)) (insert "\t \"") (end-of-line) (insert (if (eobp) "\"" "\\n\"")) (forward-line 1))) (let ((doc (buffer-string))) (kill-buffer (current-buffer)) (set-window-configuration guile-c-window-configuration) (let ((region (guile-c-find-docstring))) (goto-char (car region)) (delete-region (car region) (cdr region))) (insert doc))) (defun guile-c-find-docstring () (save-excursion (if (re-search-backward "^SCM_DEFINE" nil t) (let ((start (progn (forward-line 2) (point)))) (while (looking-at "[ \t]*\"") (forward-line 1)) (cons start (- (point) 2)))))) ;;; ;;; Others ;;; (defun guile-c-deprecate-region (start end) (interactive "r") (save-excursion (let ((marker (make-marker))) (set-marker marker end) (goto-char start) (insert "#if (SCM_DEBUG_DEPRECATED == 0)\n\n") (goto-char marker) (insert "\n#endif /* (SCM_DEBUG_DEPRECATED == 0) */\n")))) (provide 'guile-c) ;; guile-c.el ends here