cc-mode-expansions.el (6946B)
1 ;;; cc-mode-expansions.el --- C-specific expansions for expand-region -*- lexical-binding: t; -*- 2 3 ;; Copyright (C) 2012-2023 Free Software Foundation, Inc 4 5 ;; Author: François Févotte 6 ;; Based on js-mode-expansions by: Magnar Sveen <magnars@gmail.com> 7 ;; Keywords: marking region 8 9 ;; This program is free software; you can redistribute it and/or modify 10 ;; it under the terms of the GNU General Public License as published by 11 ;; the Free Software Foundation, either version 3 of the License, or 12 ;; (at your option) any later version. 13 14 ;; This program is distributed in the hope that it will be useful, 15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 ;; GNU General Public License for more details. 18 19 ;; You should have received a copy of the GNU General Public License 20 ;; along with this program. If not, see <http://www.gnu.org/licenses/>. 21 22 ;;; Commentary: 23 ;; 24 ;; Extra expansions for C-like modes that I've found useful so far: 25 ;; 26 ;; er/c-mark-statement 27 ;; Captures simple and more complex statements. 28 ;; 29 ;; er/c-mark-fully-qualified-name 30 ;; Captures identifiers composed of several '::'-separated parts. 31 ;; 32 ;; er/c-mark-function-call[-1|-2] 33 ;; Captures an identifier followed by a '()'-enclosed block. 34 ;; 35 ;; er/c-mark-statement-block[-1|-2] 36 ;; Captures a statement followed by a '{}'-enclosed block. 37 ;; This matches function definitions and if/for/... constructs. 38 ;; 39 ;; er/c-mark-vector-access[-1|-2] 40 ;; Captures an identifier followed by a '[]'-enclosed block. 41 ;; 42 ;; Feel free to contribute any other expansions for C at 43 ;; 44 ;; https://github.com/magnars/expand-region.el 45 46 ;;; Code: 47 48 (require 'expand-region-core) 49 (require 'er-basic-expansions) 50 (require 'cc-cmds) 51 52 (defun er/c-mark-statement () 53 "Mark the current C statement. 54 55 This function tries to ensure that pair-delimited substring are 56 either fully inside or fully outside the statement." 57 (interactive) 58 (unless (use-region-p) 59 (set-mark (point))) 60 61 (if (< (point) (mark)) 62 (exchange-point-and-mark)) 63 64 ;; Contract the region a bit to make the 65 ;; er/c-mark-statement function idempotent 66 (when (>= (- (point) (mark)) 2) 67 (exchange-point-and-mark) 68 (forward-char) 69 (exchange-point-and-mark) 70 (backward-char)) 71 72 (let (beg end) 73 ;; Determine boundaries of the outside-pairs region 74 (save-mark-and-excursion 75 (c-end-of-statement) 76 (er/mark-outside-pairs) 77 (setq beg (point) 78 end (mark))) 79 80 ;; Determine boundaries of the statement as given 81 ;; by c-beginning-of-statement/c-end-of-statement 82 (c-end-of-statement) 83 (exchange-point-and-mark) 84 (c-end-of-statement)(c-beginning-of-statement 1) 85 86 ;; If the two regions overlap, expand the region 87 (cond ((and (<= (point) beg) 88 (< (mark) end)) 89 (set-mark end)) 90 ((and (> (point) beg) 91 (>= (mark) end)) 92 (goto-char beg) 93 (c-end-of-statement) 94 (c-beginning-of-statement 1))))) 95 96 (defun er/c-mark-fully-qualified-name () 97 "Mark the current C++ fully qualified identifier. 98 99 This function captures identifiers composed of multiple 100 '::'-separated parts." 101 (interactive) 102 (er/mark-symbol) 103 (when (use-region-p) 104 (when (> (point) (mark)) 105 (exchange-point-and-mark)) 106 (while (er/looking-back-exact "::") 107 (backward-char 2) 108 (skip-syntax-backward "_w")) 109 (exchange-point-and-mark) 110 (while (looking-at "::") 111 (forward-char 2) 112 (skip-syntax-forward "_w")) 113 (exchange-point-and-mark))) 114 115 (defmacro er/c-define-construct (name mark-first-part open-brace doc) 116 (let ((docstring (make-symbol "docstring-tmp"))) 117 (setq docstring 118 (concat 119 doc "\n\n" 120 "This function tries to mark a region consisting of two parts:\n" 121 (format " - the first part is marked using `%s'\n" (symbol-name mark-first-part)) 122 (format " - the second part is a block beginning with %S\n\n" open-brace))) 123 `(progn 124 (defun ,(intern (concat (symbol-name name) "-1")) () 125 ,(concat docstring 126 "This function assumes that point is in the first part and the\n" 127 "region is active.\n\n" 128 (format "See also `%s'." (concat (symbol-name name) "-2"))) 129 (interactive) 130 (when (use-region-p) 131 (,mark-first-part) 132 (exchange-point-and-mark) 133 (let ((oldpos (point))) 134 (skip-syntax-forward " ") 135 (if (looking-at ,open-brace) 136 (progn (forward-sexp) 137 (exchange-point-and-mark)) 138 (goto-char oldpos))))) 139 (defun ,(intern (concat (symbol-name name) "-2")) () 140 ,(concat docstring 141 "This function assumes that the block constituting the second part\n" 142 "is already marked and active.\n\n" 143 (format "See also `%s'." (concat (symbol-name name) "-1"))) 144 (interactive) 145 (when (use-region-p) 146 (when (> (point) (mark)) 147 (exchange-point-and-mark)) 148 (when (looking-at ,open-brace) 149 (let ((beg (point)) 150 (end (progn (forward-sexp 1) 151 (point)))) 152 (goto-char beg) 153 (skip-syntax-backward " ") 154 (backward-char) 155 (deactivate-mark) 156 (,mark-first-part) 157 (set-mark end)))))))) 158 159 (er/c-define-construct er/c-mark-function-call er/c-mark-fully-qualified-name "(" 160 "Mark the current function call.") 161 (er/c-define-construct er/c-mark-statement-block er/c-mark-statement "{" 162 "Mark the current block construct (like if, for, etc.)") 163 (er/c-define-construct er/c-mark-vector-access er/c-mark-fully-qualified-name "\\[" 164 "Mark the current vector access.") 165 166 (defun er/add-cc-mode-expansions () 167 "Adds expansions for buffers in c-mode." 168 (set (make-local-variable 'er/try-expand-list) 169 (append er/try-expand-list 170 '(er/c-mark-statement 171 er/c-mark-fully-qualified-name 172 er/c-mark-function-call-1 er/c-mark-function-call-2 173 er/c-mark-statement-block-1 er/c-mark-statement-block-2 174 er/c-mark-vector-access-1 er/c-mark-vector-access-2)))) 175 176 (er/enable-mode-expansions 'c-mode #'er/add-cc-mode-expansions) 177 (er/enable-mode-expansions 'c++-mode #'er/add-cc-mode-expansions) 178 (er/enable-mode-expansions 'objc-mode #'er/add-cc-mode-expansions) 179 (er/enable-mode-expansions 'java-mode #'er/add-cc-mode-expansions) 180 (er/enable-mode-expansions 'idl-mode #'er/add-cc-mode-expansions) 181 (er/enable-mode-expansions 'pike-mode #'er/add-cc-mode-expansions) 182 (er/enable-mode-expansions 'awk-mode #'er/add-cc-mode-expansions) 183 184 (provide 'cc-mode-expansions) 185 186 ;; cc-mode-expansions.el ends here