dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

cc-mode-expansions.el (6912B)


      1 ;;; cc-mode-expansions.el --- C-specific expansions for expand-region
      2 
      3 ;; Copyright (C) 2012-2020  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