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

Chizi123
2018-11-17 5cb5f70b1872a757e93ea333b0e2dca50c6c8957
commit | author | age
5cb5f7 1 ;;; smartparens-ess.el --- Smartparens Extension for Emacs Speaks Statistics  -*- lexical-binding: t; -*-
C 2
3 ;; Copyright (c) 2015-2016 Bernhard Pröll
4
5 ;; Author: Bernhard Pröll
6 ;; Maintainer: Bernhard Pröll
7 ;; URL: https://github.com/Fuco1/smartparens
8 ;; Created: 2015-02-26
9 ;; Version: 0.2
10 ;; Keywords: abbrev convenience editing
11
12 ;; This file is NOT part of GNU Emacs.
13
14 ;; This program is free software; you can redistribute it and/or modify
15 ;; it under the terms of the GNU General Public License as published by
16 ;; the Free Software Foundation, either version 3 of the License, or
17 ;; (at your option) any later version.
18
19 ;; This program is distributed in the hope that it will be useful,
20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 ;; GNU General Public License for more details.
23
24 ;; You should have received a copy of the GNU General Public License
25 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
26
27 ;;; Commentary:
28 ;;
29 ;; This file provides some additional configuration for ESS.  To use
30 ;; it, simply add:
31 ;;
32 ;; (require 'smartparens-ess)
33 ;;
34 ;; into your configuration.  You can use this in conjunction with the
35 ;; default config or your own configuration.
36 ;;
37 ;;; Code:
38
39 (require 'smartparens)
40 (require 'rx)
41
42 (defvar ess-roxy-str)
43
44 (declare-function ess-roxy-indent-on-newline "ess-roxy")
45
46
47 ;; avoid traveling commas when slurping
48 ;; (|a, b), c ---> (|a, b, c)
49 (dolist (mode '(ess-mode inferior-ess-mode))
50   (add-to-list 'sp-sexp-suffix (list mode 'regexp "")))
51
52 ;; `sp-sexp-prefix' for ESS
53 (add-to-list 'sp-sexp-prefix
54              (list 'ess-mode 'regexp
55                    (rx (zero-or-more (or word (syntax symbol))))))
56
57 ;; slurping follows Google's R style guide
58 ;; see https://google.github.io/styleguide/Rguide.xml
59 (defun sp-ess-pre-handler (_id action _context)
60   "Remove spaces before opening parenthesis in a function call.
61 Remove redundant space around commas.
62 ID, ACTION, CONTEXT."
63   (when (equal action 'slurp-forward)
64     (let ((sxp (sp-get-thing 'back)))
65       (save-excursion
66         (goto-char (sp-get sxp :beg-prf))
67         ;; (|)   x ---> (x)
68         (when (looking-back (rx (syntax open-parenthesis)
69                                 (one-or-more space)) nil)
70           (cycle-spacing 0 nil 'single-shot))
71         (cond
72          ;; (|)if(cond) ---> (|if (cond))
73          ((member (sp-get sxp :prefix) '("if" "for" "while"))
74           (goto-char (sp-get sxp :beg))
75           (cycle-spacing 1 nil 'single-shot))
76          ;; (|)v [,2] <- if(x > 1) ---> (v[,2] <- if (x > 1))
77          ((and
78            (member (sp-get sxp :op) '("[" "("))
79            (equal (sp-get sxp :prefix) "")
80            (looking-back
81             (rx (and (not-char "%" ",")
82                      (not (syntax close-parenthesis)))
83                 (one-or-more space)) nil)
84            (not (member
85                  (save-excursion
86                    (sp-backward-sexp)
87                    (thing-at-point 'word 'noprop))
88                  '("if" "for" "while"))))
89           (cycle-spacing 0 nil 'single-shot))
90          ;; (|[...])%in% ---> ([...] %in%|)
91          ((or (looking-at "%") (looking-back "%" nil))
92           (just-one-space))
93          ;; (|)a , b,    c ---> (|a, b, c)
94          ((looking-back
95            (rx (zero-or-more space) "," (zero-or-more space))
96            (line-beginning-position) 'greedy)
97           (replace-match ", "))))))
98   (when (equal action 'slurp-backward)
99     (let ((sxp (sp-get-thing)))
100       (save-excursion
101         (goto-char (sp-get sxp :end))
102         ;; x  (|) ---> (x)
103         (when (looking-at (rx (one-or-more space)
104                               (syntax close-parenthesis)))
105           (cycle-spacing 0 nil 'single-shot))
106         ;; if(cond){} (|) ---> (if (cond) {}|)
107         (cond ((member (sp-get sxp :prefix) '("if" "for" "while"))
108                (goto-char (sp-get sxp :beg))
109                (cycle-spacing 1 nil 'single-shot))
110               ;; for style reasons there should be a space before curly
111               ;; brackets and binary operators
112               ((and (member (sp-get sxp :op) '("{" "%"))
113                     (not (looking-at (rx (syntax close-parenthesis)))))
114                (cycle-spacing 1 nil 'single-shot))
115               ;; v[2](|) ---> (v[2]|)
116               ((and
117                 (not (member (thing-at-point 'word 'noprop)
118                              '("if" "for" "while")))
119                 (looking-at
120                  (rx (and (zero-or-more space)
121                           (not-char "{")
122                           (or (syntax close-parenthesis)
123                               (char "(")
124                               (char "["))))))
125                (cycle-spacing 0 nil 'single-shot))
126               ;; 1 , 2 (|) ---> (1, 2)
127               ((looking-at
128                 (rx (zero-or-more space) "," (zero-or-more space)))
129                (replace-match ", ")))))))
130
131 ;; function(x) {|} ---> function(x) {\n|\n}
132 ;; ##' \tabular{rrr}{|} --->
133 ;; ##' \tabular{rrr}{
134 ;; ##'   |
135 ;; ##' }
136 (defun sp-ess-open-sexp-indent (&rest _args)
137   "Open new brace or bracket with indentation.
138 ARGS."
139   (if (and (fboundp 'ess-roxy-entry-p) (ess-roxy-entry-p))
140       (progn
141         (save-excursion (ess-roxy-indent-on-newline))
142         (when (looking-back ess-roxy-str nil)
143           (cycle-spacing 3 nil t)))
144     (newline)
145     (indent-according-to-mode)
146     (forward-line -1)
147     (indent-according-to-mode)))
148
149 (defun sp-ess-roxy-str-p (_id action _context)
150   "Test if looking back at `ess-roxy-re'.
151 ID, ACTION, CONTEXT."
152   (when (and (boundp 'ess-roxy-re) (eq action 'insert))
153     (sp--looking-back-p ess-roxy-re)))
154
155 (sp-with-modes 'ess-mode
156   (sp-local-pair "{" nil
157                  :pre-handlers '(sp-ess-pre-handler)
158     ;; the more reasonable C-j interferes with default binding for
159     ;; `ess-eval-line'
160                  :post-handlers '((sp-ess-open-sexp-indent "M-j")))
161   (sp-local-pair "(" nil
162                  :pre-handlers '(sp-ess-pre-handler)
163                  :post-handlers '((sp-ess-open-sexp-indent "M-j")))
164   (sp-local-pair "[" nil
165                  :pre-handlers '(sp-ess-pre-handler)
166                  :post-handlers '((sp-ess-open-sexp-indent "M-j")))
167   (sp-local-pair "'" nil
168                  :unless '(sp-ess-roxy-str-p sp-in-comment-p sp-in-string-quotes-p)))
169
170 ;;; roxygen2 markup
171 ;; see https://cran.r-project.org/web/packages/roxygen2/vignettes/formatting.html
172 (sp-with-modes 'ess-mode
173   (sp-local-pair "\\strong{" "}"
174                  :when '(sp-in-comment-p)
175                  :trigger "\\strong")
176   (sp-local-pair "\\emph{" "}"
177                  :when '(sp-in-comment-p)
178                  :trigger "\\emph")
179   (sp-local-pair "\\code{" "}"
180                  :when '(sp-in-comment-p)
181                  :trigger "\\code")
182   (sp-local-pair "\\url{" "}"
183                  :when '(sp-in-comment-p)
184                  :trigger "\\url")
185   (sp-local-pair "\\link{" "}"
186                  :when '(sp-in-comment-p)
187                  :trigger "\\link")
188   (sp-local-pair "\\href{" "}"
189                  :when '(sp-in-comment-p)
190                  :trigger "\\href"
191                  :suffix "{[^}]*}")
192   (sp-local-pair "\\email{" "}"
193                  :when '(sp-in-comment-p)
194                  :trigger "\\email")
195   (sp-local-pair "\\pkg{" "}"
196                  :when '(sp-in-comment-p)
197                  :trigger "\\pkg")
198   (sp-local-pair "\\item{" "}"
199                  :when '(sp-in-comment-p)
200                  :post-handlers '((sp-ess-open-sexp-indent "M-j"))
201                  :trigger "\\item{")
202   (sp-local-pair "\\enumerate{" "}"
203                  :when '(sp-in-comment-p)
204                  :post-handlers '((sp-ess-open-sexp-indent "M-j"))
205                  :trigger "\\enumerate")
206   (sp-local-pair "\\itemize{" "}"
207                  :when '(sp-in-comment-p)
208                  :post-handlers '((sp-ess-open-sexp-indent "M-j"))
209                  :trigger "\\itemize")
210   (sp-local-pair "\\describe{" "}"
211                  :when '(sp-in-comment-p)
212                  :post-handlers '((sp-ess-open-sexp-indent "M-j"))
213                  :trigger "\\describe")
214   (sp-local-pair "\\eqn{" "}"
215                  :when '(sp-in-comment-p)
216                  :trigger "\\eqn")
217   (sp-local-pair "\\deqn{" "}"
218                  :when '(sp-in-comment-p)
219                  :trigger "\\deqn")
220   (sp-local-pair "\\tabular{" "}"
221                  :when '(sp-in-comment-p)
222                  :trigger "\\tabular"
223                  :post-handlers '((sp-ess-open-sexp-indent "M-j"))
224                  :suffix "{[^}]*}"))
225
226
227 (provide 'smartparens-ess)
228 ;;; smartparens-ess ends here