;;; c-conf.el --- configurations for C-mode -*- lexical-binding: t; -*- ;; Copyright (C) 2021 李俊緯 ;; Author: Durand ;; Keywords: c, convenience, languages ;; 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 3 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, see . ;;; Commentary: ;; My configurations for editing C files. ;;; Code: (setq c-macro-preprocessor "gcc -E -C -o - -") ;; We can achieve the functionality of the original binding ;; comment-region by comment-dwim bound to "M-;". (define-key c-mode-map (vector 3 3) #'compile) ;; This proves to be too convenient not to bind. (define-key c-mode-map (vector 'S-tab) #'ff-find-other-file) ;;; prefix map (defvar durand-c-prefix-map (make-sparse-keymap) "The keymap of my custom functions. This will be bound to the key ù.") (let ((map durand-c-prefix-map)) (define-key map (vector ?i) #'durand-c-include) (define-key map (vector ?p) #'c-generate-pragma) (define-key map (vector ?t) #'c-generate-test)) ;; generate pragmas automatically. (define-key c-mode-map (vector ?ù) durand-c-prefix-map) (defun c-generate-pragma () "Generate default pragmas for a C header file. If invoked on a C file, include the corresponding header file." (interactive) (cond ((not (derived-mode-p 'c-mode 'c++-mode))) ((string-match-p "hp*$"(buffer-name)) (insert "#ifndef ") (insert (replace-regexp-in-string "\\." "_" (upcase (file-name-nondirectory (buffer-file-name))))) (newline) (insert "#define ") (insert (replace-regexp-in-string "\\." "_" (upcase (file-name-nondirectory (buffer-file-name))))) (newline 2) (insert "#endif") (forward-line -1)) (t (insert (format "#include \"%s\"" (replace-regexp-in-string "c\\(p*\\)$" "h\\1" (buffer-name)))) (newline)))) (defun durand-c-include (&optional arg) "Include a library. If ARG is non-nil, ask for the type of the include: whether the angle bracket type or the quote type." (interactive) (let* ((library (read-string "Include: ")) (type (cond ((null arg) (cond ((string-match-p "^\\(std\\|string.h\\)" library) 'angle) ('quote))) (t (intern (completing-read "Which type? " '("angle" "quote") nil t)))))) (save-restriction (widen) (save-excursion (goto-char (point-min)) (re-search-forward "^#include" nil t) (forward-line 0) (insert "#include " (cond ((eq type 'angle) "<") ((eq type 'quote) "\"")) library (cond ((eq type 'angle) ">") ((eq type 'quote) "\"")) "\n"))))) (defun c-generate-test () "Generate or find a test file for the current C file." (interactive) (cond ((derived-mode-p 'c-mode)) ((user-error "Not in C-mode"))) (let* ((f-name (buffer-file-name)) (base (file-name-base f-name)) (t-name (cond ((null f-name) (user-error "Buffer not associated to a file")) ((expand-file-name (expand-file-name (format "check_%s.c" base) "test") (file-name-directory f-name)))))) (cond ((file-exists-p t-name)) ((write-region (format "#include \"../%s.h\"\n\n%s" base "int main(int argc, char **argv)\n{\n return 0;\n}\n") nil t-name))) (find-file t-name))) (provide 'c-conf) ;;; c-conf.el ends here