mirror of https://github.com/Chizi123/.emacs.d.git

Chizi123
2018-11-19 a4b9172aefa91861b587831e06f55b1e19f3f3be
commit | author | age
5cb5f7 1 ;;; smartparens-rust.el --- Additional configuration for Rust based modes.  -*- lexical-binding: t; -*-
C 2
3 ;; Copyright (C) 2015 Wilfred Hughes
4
5 ;; Created: 3 November 2015
6 ;; Keywords: abbrev convenience editing
7 ;; URL: https://github.com/Fuco1/smartparens
8
9 ;; This file is not part of GNU Emacs.
10
11 ;;; License:
12
13 ;; This file is part of Smartparens.
14
15 ;; Smartparens is free software; you can redistribute it and/or modify
16 ;; it under the terms of the GNU General Public License as published by
17 ;; the Free Software Foundation, either version 3 of the License, or
18 ;; (at your option) any later version.
19
20 ;; Smartparens is distributed in the hope that it will be useful,
21 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23 ;; GNU General Public License for more details.
24
25 ;; You should have received a copy of the GNU General Public License
26 ;; along with Smartparens.  If not, see <http://www.gnu.org/licenses/>.
27
28 ;;; Commentary:
29
30 ;; This file provides some additional configuration for Rust.  To use
31 ;; it, simply add:
32 ;;
33 ;; (require 'smartparens-config)
34 ;;
35 ;; alternatively, you can explicitly load these preferences:
36 ;;
37 ;; (require 'smartparens-rust)
38 ;;
39 ;; in your configuration.
40
41 ;; For more info, see github readme at
42 ;; https://github.com/Fuco1/smartparens
43
44 ;;; Code:
45 (require 'smartparens)
46
47 (declare-function rust-mode "rust-mode")
48
49 (defun sp-in-rust-lifetime-context (&rest _args)
50   "Return t if point is in a Rust context where ' represents a lifetime.
51 If we return nil, ' should be used for character literals.
52 ARGS."
53   (or
54    (condition-case nil
55        ;; If point is just after a &', it's probably a &'foo.
56        (save-excursion
57          (backward-char 2)
58          (looking-at "&"))
59      ;; If we're at the beginning of the buffer, just carry on.
60      (beginning-of-buffer))
61    ;; If point is inside < > it's probably a parameterised function.
62    (let ((paren-pos (nth 1 (syntax-ppss))))
63      (and paren-pos
64           (save-excursion
65             (goto-char paren-pos)
66             (looking-at "<"))))))
67
68 (defun sp-rust-skip-match-angle-bracket (_ms _mb me)
69   "Non-nil if we should ignore the bracket as valid delimiter."
70   (save-excursion
71     (goto-char me)
72     (let ((on-fn-return-type
73            (sp--looking-back-p (rx "->") nil))
74           (on-match-branch
75            (sp--looking-back-p (rx "=>") nil))
76           (on-comparison
77            (sp--looking-back-p (rx (or
78                                     (seq space "<")
79                                     (seq space ">")
80                                     (seq space "<<")
81                                     (seq space ">>")))
82                                nil)))
83       (or on-comparison on-fn-return-type on-match-branch))))
84
85 (defun sp-rust-filter-angle-brackets (_id action context)
86   "Non-nil if we should allow ID's ACTION in CONTEXT for angle brackets."
87   ;; See the docstring for `sp-pair' for the possible values of ID,
88   ;; ACTION and CONTEXT.
89   (cond
90    ;; Inside strings, don't do anything with < or >.
91    ((eq context 'string)
92     nil)
93    ;; Don't do any smart pairing inside comments either.
94    ((eq context 'comment)
95     nil)
96    ;; Otherwise, we're in code.
97    ((eq context 'code)
98     (let ((on-fn-return-type
99            (looking-back (rx "->") nil))
100           (on-match-branch
101            (looking-back (rx "=>") nil))
102           (on-comparison
103            (looking-back (rx (or
104                               (seq space "<")
105                               (seq space ">")
106                               (seq space "<<")
107                               (seq space ">>")))
108                          nil)))
109       (cond
110        ;; Only insert a matching > if we're not looking at a
111        ;; comparison.
112        ((eq action 'insert)
113         (and (not on-comparison) (not on-fn-return-type) (not on-match-branch)))
114        ;; Always allow wrapping in a pair if the region is active.
115        ((eq action 'wrap)
116         (not on-match-branch))
117        ;; When pressing >, autoskip if we're not looking at a
118        ;; comparison.
119        ((eq action 'autoskip)
120         (and (not on-comparison) (not on-fn-return-type) (not on-match-branch)))
121        ;; Allow navigation, highlighting and strictness checks if it's
122        ;; not a comparison.
123        ((eq action 'navigate)
124         (and (not on-comparison) (not on-fn-return-type) (not on-match-branch))))))))
125
126 (sp-with-modes '(rust-mode)
127   (sp-local-pair "'" "'"
128                  :unless '(sp-in-comment-p sp-in-string-quotes-p sp-in-rust-lifetime-context)
129                  :post-handlers'(:rem sp-escape-quotes-after-insert))
130   (sp-local-pair "<" ">"
131                  :when '(sp-rust-filter-angle-brackets)
132                  :skip-match 'sp-rust-skip-match-angle-bracket))
133
134 ;; Rust has no sexp suffices.  This fixes slurping
135 ;; (|foo).bar -> (foo.bar)
136 (add-to-list 'sp-sexp-suffix (list #'rust-mode 'regexp ""))
137
138 (provide 'smartparens-rust)
139
140 ;;; smartparens-rust.el ends here