-
Notifications
You must be signed in to change notification settings - Fork 2
/
cme.el
274 lines (255 loc) · 11.2 KB
/
cme.el
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
;;; cme.el --- Main CME entry point
;; Copyright (C) 2021 Consciencia
;; Author: Consciencia <[email protected]>
;; Version: 1.0.0
;; Keywords: c c++ cme cedet
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; :(
;;; Code:
(setq *cme-packages-refreshed* nil)
(loop for package in '(company company-c-headers s pcre2el)
if (not (package-installed-p package))
do (progn
(when (not *cme-packages-refreshed*)
(package-refresh-contents)
(setq *cme-packages-refreshed* t))
(package-install package)))
(require 's)
(require 'cl)
(require 'json)
(require 'pcre2el)
(require 'cc-mode)
(require 'data-debug)
(require 'seq)
(require 'mode-local)
(require 'ido)
(require 'company)
(require 'company-semantic)
(require 'company-c-headers)
(require 'ede)
(require 'ede/cpp-root)
(require 'semantic/db)
(require 'semantic)
(require 'semantic/idle)
(require 'semantic/symref)
(require 'semantic/symref/grep)
(require 'semantic/symref/list)
(require 'semantic/symref/filter)
(require 'semantic/doc)
(require 'semantic/ia)
(require 'semantic/chart)
(require 'semantic/ctxt)
(require 'semantic/bovine/c)
(require 'semantic/analyze)
(require 'semantic/dep)
(require 'srecode)
(require 'srecode/fields)
(require 'cme-utils)
(require 'cme-semanticdb-grep)
(require 'cme-ede-generic-proj)
(require 'cme-cpp-root)
(require 'cme-misc)
(require 'cme-company)
(require 'cme-db-find)
(require 'cme-db)
(require 'cme-refs)
(require 'cme-find)
(require 'cme-ia)
(require 'cme-symref)
(require 'cme-search)
(require 'cme-index)
(require 'cme-doc)
(require 'cme-complete)
(require 'cme-analyze)
(require 'cme-senator)
(require 'cme-c)
(defun cme-init (&rest args)
(interactive)
(setq semantic-new-buffer-setup-functions
(loop for e in semantic-new-buffer-setup-functions
if (not (or (equal (car e) 'python-mode)
(equal (car e) 'js-mode)
(equal (car e) 'html-mode)))
collect e))
(setq-default semantic-idle-breadcrumbs-format-tag-function 'semantic-format-tag-summarize
semantic-idle-work-parse-neighboring-files-flag nil
semantic-idle-work-update-headers-flag nil
semantic-complete-inline-analyzer-displayer-class 'semantic-displayer-tooltip
semantic-edits-verbose-flag t
;; Use (semantic-symref-detect-symref-tool) for autodetecting
;; symref tool. Currently, we dont want to use that. Grep is
;; by far the best option If you have modern CPU.
;; Anyway, global is kinda buggy and cscope is not very used.
semantic-symref-tool 'grep
senator-step-at-tag-classes nil
senator-step-at-start-end-tag-classes '(function)
speedbar-use-images nil
speedbar-use-imenu-flag t)
(global-semanticdb-minor-mode t)
(global-semantic-idle-scheduler-mode t)
(global-semantic-mru-bookmark-mode t)
(global-semantic-highlight-edits-mode t)
(global-semantic-idle-summary-mode t)
(global-semantic-highlight-func-mode t)
;; Disabled because decoration mode awfully slows down parsing of
;; larger chunks of unparsed files.
;; Also, when turning on, it will iterate all buffers and turns itself on
;; in every buffer managed by semantic which is very slow when many
;; buffers are opened.
;; Because of that, its not good idea to switch it off and on when
;; parsing.
;; Below, it is enabled on per buffer basis using idle timer.
(global-semantic-decoration-mode -1)
(global-semantic-idle-breadcrumbs-mode t)
;; idle breadcrumbs are better, but are in conflict
;; with stickyfunc, so its disabled.
(global-semantic-stickyfunc-mode -1)
;; We dont want this globally, it kinds of annoys in some situations.
(global-semantic-show-unmatched-syntax-mode -1)
;; Activate decoration mode for current buffer only after some seconds
;; of idling. This way, no slow down due to decorations happen during
;; bulk file parsing.
(run-with-idle-timer 2 t 'cme-enable-decorations-locally)
(cme-db-enable-grep)
(global-ede-mode 1)
(semantic-mode 1)
;; Support for elisp slowes things down and I dont have time to find
;; out why. Another thing is that output from semantic is used only
;; for imenu so its not critical.
;;
;; (add-to-list 'semantic-new-buffer-setup-functions
;; '(emacs-lisp-mode . semantic-default-elisp-setup))
(add-to-list 'semantic-inhibit-functions
(lambda ()
(not (or (equal major-mode 'c-mode)
(equal major-mode 'c++-mode)
;; (equal major-mode 'emacs-lisp-mode)
))))
(advice-add 'save-buffer :after
(lambda (&rest args)
(if (or (equal major-mode 'c-mode)
(equal major-mode 'c++-mode)
;; (equal major-mode 'emacs-lisp-mode)
)
(save-mark-and-excursion
(cme-reparse-buffer)))))
;; Overriden in order to make CEDET not crash due to invalid usage
;; of file-exists-p.
(advice-add #'file-exists-p
:around
(lambda (oldfn filename)
(if filename
(funcall oldfn filename))))
(loop for mode in '(c-mode-hook c++-mode-hook)
do (add-hook mode
(lambda ()
(set (make-local-variable 'company-backends)
'((company-c-headers
company-semantic
company-files)))
(local-set-key (kbd ".")
(lambda ()
(interactive)
(if (cme-is-prefix-pointer-p)
(insert "->")
(insert ".")))))))
(when (and (plist-member args :configure-keys)
(plist-get args :configure-keys))
(loop for mode in '(c-mode-hook c++-mode-hook)
do (add-hook mode
(lambda ()
(local-set-key (kbd "M-.") 'cme-jump)
(local-set-key (kbd "C-.") 'cme-find-anything)
(local-set-key (kbd "C-r") 'cme-browse-local-tags)
(local-set-key (kbd "M--") 'cme-symref)
(local-set-key (kbd "M-,") 'cme-pop-mark)
(local-set-key (kbd "M-*") 'cme-doc)
(local-set-key (kbd "C-,") 'cme-proto-impl-toggle)
(local-set-key (kbd "M-r M-v") 'cme-rename-local-var)
(local-set-key (kbd "M-<next>") 'cme-next-tag)
(local-set-key (kbd "M-<prior>") 'cme-previous-tag)
(local-set-key (kbd "M-p") 'cme-follow-ref-up)
(local-set-key (kbd "M-c") 'cme-find-subclasses)
(local-set-key (kbd "M-f") 'cme-fold-tag-toggle)
(local-set-key (kbd "M-d") 'cme-mark-tag)
(local-set-key (kbd "M-g") 'cme-reparse-buffer)
(local-set-key (kbd "<tab>")
'company-indent-or-complete-common))))))
(defalias 'cme-next-tag 'senator-next-tag)
(defalias 'cme-previous-tag 'senator-previous-tag)
(defalias 'cme-fold-tag-toggle 'senator-fold-tag-toggle)
(defalias 'cme-reparse-buffer 'semantic-force-refresh)
(defalias 'cme-compile-project 'ede-compile-project)
(defalias 'cme-list-includes 'semanticdb-find-adebug-scanned-includes)
;; In major version 27 and newer, symbols with displayor in name were
;; renamed so that word displayer is used instead.
(when (< emacs-major-version 27)
(defalias 'semantic-displayer-current-focus
'semantic-displayor-current-focus)
(defalias 'semantic-displayer-focus-abstract-child-p
'semantic-displayor-focus-abstract-child-p)
(defalias 'semantic-displayer-cleanup
'semantic-displayor-cleanup)
(defalias 'semantic-displayer-traditional
'semantic-displayor-traditional)
(defalias 'semantic-displayer-tooltip
'semantic-displayor-tooltip))
(if (version< emacs-version "28")
;; Byte compile all CME functions on startup.
(mapatoms (lambda (sym)
(when (and (s-starts-with-p "cme-" (format "%s" sym))
(fboundp sym))
(let ((byte-compile-log-warning-function
(lambda (&rest args))))
(byte-compile sym)))))
;; Native compile all CME functions on startup.
(mapatoms (lambda (sym)
(when (and (s-starts-with-p "cme-" (format "%s" sym))
(fboundp sym))
(let ((byte-compile-log-warning-function
(lambda (&rest args))))
(ignore-error (native-compile sym)))))))
;; Detect emacs version changes and remove semantic DB when it happens.
;; DB store tags as eieio object dumps and sometimes, new emacs version
;; breaks backward compatibility which CEDET fails to resolve properly.
;; Instead, all just became buggy.
(let* ((write-file (lambda (filename data)
(ignore-errors
(let ((coding-system-for-write 'binary)
(write-region-annotate-functions nil)
(write-region-post-annotation-function nil))
(write-region data nil filename nil :silent)
nil))))
(read-file (lambda (filename)
(ignore-errors
(with-temp-buffer
(set-buffer-multibyte nil)
(setq buffer-file-coding-system 'binary)
(insert-file-contents-literally filename)
(buffer-substring-no-properties (point-min)
(point-max))))))
(root (expand-file-name user-emacs-directory))
(version-filename (concat root "cme-last-ver.txt"))
(version (funcall read-file version-filename)))
(when (not (or (equal version nil)
(equal version (emacs-version))))
(delete-directory (concat root "semanticdb") t t))
(funcall write-file version-filename (emacs-version)))
(cme-silence-eldoc-for-funcs yes-or-no-p
y-or-n-p
read-from-minibuffer
read-string
read-regexp
save-some-buffers)
(provide 'cme)
;;; cme.el ends here