]> code.delx.au - gnu-emacs-elpa/blob - packages/ada-mode/gpr-wisi.el
Merge commit '0cda39255827f283e7578cd469ae42daad9556a2' from js2-mode
[gnu-emacs-elpa] / packages / ada-mode / gpr-wisi.el
1 ;; gpr-wisi.el --- Indentation engine for gpr mode, using the wisi parser -*- lexical-binding:t -*-
2 ;;
3 ;; Copyright (C) 2013 - 2015 Free Software Foundation, Inc.
4 ;;
5 ;; Author: Stephen Leake <stephen_leake@member.fsf.org>
6 ;;
7 ;; This file is part of GNU Emacs.
8 ;;
9 ;; GNU Emacs 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 ;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
21 ;;
22 ;;; History: first version Jan 2013
23 ;;
24 ;;; code style
25 ;;
26 ;; I don't use 'pcase', because it gives _really_ confusing errors
27 ;; when I forget a ')' somewhere. Even worse, the error message is
28 ;; given when you use edebug on a defun, not when you eval it. This
29 ;; code is hard enough to debug!
30 ;;
31 ;;;;
32
33 ;; we reuse some stuff from ada-mode
34 (require 'ada-indent-user-options)
35 (require 'gpr-grammar-wy)
36 (require 'gpr-mode)
37 (require 'wisi)
38
39 (defconst gpr-wisi-class-list
40 '(
41 block-start
42 block-middle
43 block-end
44 close-paren
45 list-break
46 open-paren
47 statement-end
48 statement-other
49 statement-start
50 ))
51
52 (defun gpr-wisi-indent-cache (offset cache)
53 "Return indentation of OFFSET relative to indentation of line containing CACHE
54 or containing ancestor of CACHE that is at a line beginning."
55 (let ((indent (current-indentation)))
56 (while (and cache
57 (not (= (current-column) indent)))
58 (when (eq 'WHEN (wisi-cache-token cache))
59 (setq offset (+ offset ada-indent-when)))
60 (setq cache (wisi-goto-containing cache))
61 (setq indent (current-indentation)))
62 (+ (current-indentation) offset)
63 ))
64
65 (defun gpr-wisi-indent-containing (offset cache)
66 "Return indentation of OFFSET relative to containing ancestor of CACHE that is at a line beginning."
67 (gpr-wisi-indent-cache offset (wisi-goto-containing cache)))
68
69 (defun gpr-wisi-before-cache ()
70 (let ((cache (wisi-get-cache (point))))
71 (when cache
72 (cl-ecase (wisi-cache-class cache)
73 (block-start (wisi-indent-start ada-indent (wisi-backward-cache)))
74 (block-end (wisi-indent-start 0 cache))
75 (block-middle
76 (wisi-indent-start
77 (if (eq (wisi-cache-token cache) 'WHEN) ada-indent-when 0)
78 cache))
79 (close-paren (wisi-indent-paren 0))
80 (open-paren nil); let after-keyword handle it
81 (statement-start
82 (if (not (wisi-get-containing-cache cache))
83 ;; at bob
84 0
85 ;; not at bob
86 (gpr-wisi-indent-containing ada-indent cache)))
87
88 (statement-end
89 (gpr-wisi-indent-containing ada-indent-broken cache))
90 ))
91 ))
92
93 (defun gpr-wisi-after-cache ()
94 (let ((cache (wisi-backward-cache)))
95 (if (not cache)
96 ;; bob
97 0
98 (cl-ecase (wisi-cache-class cache)
99 (block-end
100 (wisi-indent-current 0))
101
102 (block-middle
103 (cl-case (wisi-cache-token cache)
104 (WHEN
105 (gpr-wisi-indent-cache ada-indent-broken cache))
106 (t
107 (gpr-wisi-indent-cache ada-indent cache))
108 ))
109
110 (block-start
111 (cl-case (wisi-cache-token cache)
112 (EQUAL_GREATER
113 (gpr-wisi-indent-containing ada-indent cache))
114 (t
115 (gpr-wisi-indent-cache ada-indent cache))
116 ))
117
118 (list-break
119 ;; test/gpr/simple.gpr
120 ;; type GNAT_Version_Type
121 ;; is ("7.0.1",
122 ;; "6.2.2", "6.2.1",
123 ;; "GPL-2012", "GPL-2011");
124 ;;
125 ;; for Source_Dirs use
126 ;; ("../auto",
127 ;; External ("GNAT_VERSION") & "/foo",
128 ;; "../../1553");
129 (wisi-goto-containing cache)
130 (1+ (current-column)))
131
132 (open-paren
133 (1+ (current-column)))
134
135 (statement-end
136 (wisi-indent-start 0 cache))
137
138 ((statement-other close-paren)
139 ;; test/gpr/simple.gpr
140 ;; ) & Style_Checks
141 ;; & Standard_Common.Compiler'Default_Switches;
142 ;;
143 ;; for Source_Dirs use
144 ;; ("../auto",
145 (wisi-indent-start ada-indent-broken cache))
146
147 (statement-start
148 ;; test/gpr/simple.gpr
149 ;; type GNAT_Version_Type
150 ;; is ("7.0.1",
151 ;; hanging
152 (gpr-wisi-indent-cache ada-indent-broken cache))
153 ))
154 ))
155
156 (defun gpr-wisi-post-parse-fail ()
157 "For `wisi-post-parse-fail-hook'."
158 ;; keep it simple :)
159 nil)
160
161 (defun gpr-wisi-which-function ()
162 "For `gpr-which-function'."
163 (wisi-validate-cache (point))
164 (let ((cache (wisi-backward-cache)))
165 (while (and cache
166 (not (and
167 (memq (wisi-cache-nonterm cache) '(package_spec simple_project_declaration))
168 (eq (wisi-cache-class cache) 'statement-start))))
169 (setq cache (wisi-goto-containing cache)))
170 (when cache
171 (wisi-forward-token); package | project
172 (wisi-token-text (wisi-forward-token)); name
173 )))
174
175 ;;; debugging
176 (defun gpr-wisi-debug-keys ()
177 "Add debug key definitions to `gpr-mode-map'."
178 (interactive)
179 (define-key gpr-mode-map "\M-h" 'wisi-show-containing-or-previous-cache)
180 (define-key gpr-mode-map "\M-j" 'wisi-show-cache)
181 (define-key gpr-mode-map "\M-k" 'wisi-show-token)
182 )
183
184 ;;;;
185 (defun gpr-wisi-setup ()
186 "Set up a buffer for parsing Ada files with wisi."
187 (wisi-setup '(gpr-wisi-before-cache
188 gpr-wisi-after-cache)
189 'gpr-wisi-post-parse-fail
190 gpr-wisi-class-list
191 gpr-grammar-wy--keyword-table
192 gpr-grammar-wy--token-table
193 gpr-grammar-wy--parse-table)
194
195 (setq gpr-indent-statement 'wisi-indent-statement)
196 (set (make-local-variable 'comment-indent-function) 'wisi-comment-indent)
197 )
198
199 (add-hook 'gpr-mode-hook 'gpr-wisi-setup)
200
201 (setq gpr-which-function 'gpr-wisi-which-function)
202
203 (setq gpr-show-parse-error 'wisi-show-parse-error)
204
205 (provide 'gpr-wisi)
206 (provide 'gpr-indent-engine)
207
208 ;; end of file