forked from company-mode/company-mode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathcompany-dabbrev-code.el
More file actions
187 lines (162 loc) · 7.59 KB
/
Copy pathcompany-dabbrev-code.el
File metadata and controls
187 lines (162 loc) · 7.59 KB
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
;;; company-dabbrev-code.el --- dabbrev-like company-mode backend for code -*- lexical-binding: t -*-
;; Copyright (C) 2009-2011, 2013-2016, 2021-2025 Free Software Foundation, Inc.
;; Author: Nikolaj Schumacher
;; This file is part of GNU Emacs.
;; GNU Emacs 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.
;; GNU Emacs 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 GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;;
;;; Code:
(require 'company)
(require 'company-dabbrev)
(require 'cl-lib)
(defgroup company-dabbrev-code nil
"dabbrev-like completion backend for code."
:group 'company)
(defcustom company-dabbrev-code-modes
'(prog-mode
batch-file-mode csharp-mode css-mode erlang-mode haskell-mode jde-mode
lua-mode python-mode)
"Modes that use `company-dabbrev-code'.
In all these modes (and their derivatives) `company-dabbrev-code' will
complete only symbols, not text in comments or strings. In other modes
`company-dabbrev-code' will pass control to other backends
\(e.g. `company-dabbrev'\). Value t means complete in all modes."
:type '(choice (repeat :tag "Some modes" (symbol :tag "Major mode"))
(const :tag "All modes" t)))
(defcustom company-dabbrev-code-other-buffers t
"Determines whether `company-dabbrev-code' should search other buffers.
If `all', search all other buffers, except the ignored ones. If t, search
buffers with the same major mode. If `code', search all
buffers with major modes in `company-dabbrev-code-modes', or derived from one of
them. This can also be a function that takes the current buffer as
parameter and returns a list of major modes to search. See also
`company-dabbrev-code-time-limit'."
:type '(choice (const :tag "Off" nil)
(const :tag "Same major mode" t)
(const :tag "Code major modes" code)
(const :tag "All" all)
(function :tag "Function to return similar major-modes" group)))
(defcustom company-dabbrev-code-time-limit .1
"Determines how long `company-dabbrev-code' should look for matches."
:type '(choice (const :tag "Off" nil)
(number :tag "Seconds")))
(defcustom company-dabbrev-code-everywhere nil
"Non-nil to offer completions in comments and strings."
:type 'boolean)
(defcustom company-dabbrev-code-ignore-case nil
"Non-nil to ignore case when collecting completion candidates."
:type 'boolean)
(defcustom company-dabbrev-code-completion-styles nil
"Non-nil to use the completion styles for fuzzy matching."
:type '(choice (const :tag "Prefix matching only" nil)
(const :tag "Matching according to `completion-styles'" t)
(list :tag "Custom list of styles" symbol))
:package-version '(company . "1.0.0"))
(defvar-local company-dabbrev--boundaries nil)
(defvar-local company-dabbrev-code--sorted nil)
(defun company-dabbrev-code--make-regexp (prefix)
(let ((prefix-re
(cond
((string-empty-p prefix)
"\\([a-zA-Z]\\|\\s_\\)")
((not company-dabbrev-code-completion-styles)
(regexp-quote prefix))
(t
;; Use the cache at least after 2 chars. We could also cache
;; earlier, for users who set company-min-p-l to 1 or 0.
(let ((prefix (if (>= (length prefix) 2)
(substring prefix 0 2)
prefix)))
(concat
"\\(\\sw\\|\\s_\\)*"
(mapconcat #'regexp-quote
(mapcar #'string prefix)
"\\(\\sw\\|\\s_\\)*")))))))
(concat "\\_<" prefix-re "\\(\\sw\\|\\s_\\)*\\_>")))
;;;###autoload
(defun company-dabbrev-code (command &optional arg &rest rest)
"dabbrev-like `company-mode' backend for code.
The backend looks for all symbols in the current buffer that aren't in
comments or strings."
(interactive (list 'interactive))
(cl-case command
(interactive (company-begin-backend 'company-dabbrev-code))
(prefix (and (or (eq t company-dabbrev-code-modes)
(cl-some #'derived-mode-p company-dabbrev-code-modes))
(or company-dabbrev-code-everywhere
(not (company-in-string-or-comment)))
(company-grab-symbol-parts)))
(candidates (company-dabbrev--candidates arg (car rest)))
(adjust-boundaries (and company-dabbrev-code-completion-styles
(company--capf-boundaries
company-dabbrev--boundaries)))
(expand-common (company-dabbrev-code--expand-common arg (car rest)))
(kind 'text)
(sorted company-dabbrev-code--sorted)
(no-cache t)
(ignore-case company-dabbrev-code-ignore-case)
(match (when company-dabbrev-code-completion-styles
(company--match-from-capf-face arg)))
(duplicates t)))
(defun company-dabbrev-code--expand-common (prefix suffix)
(when company-dabbrev-code-completion-styles
(let ((completion-styles (if (listp company-dabbrev-code-completion-styles)
company-dabbrev-code-completion-styles
completion-styles)))
(company--capf-expand-common prefix suffix
(company-dabbrev-code--table prefix)))))
(defun company-dabbrev--candidates (prefix suffix)
(let* ((case-fold-search company-dabbrev-code-ignore-case))
(company-dabbrev-code--filter
prefix suffix
(company-dabbrev-code--table prefix))))
(defun company-dabbrev-code--table (prefix)
(let ((regexp (company-dabbrev-code--make-regexp prefix)))
(company-cache-fetch
'dabbrev-code-candidates
(lambda ()
(company-dabbrev--search
regexp
company-dabbrev-code-time-limit
(pcase company-dabbrev-code-other-buffers
(`t (list major-mode))
(`code company-dabbrev-code-modes)
(`all `all)
((pred functionp) (funcall company-dabbrev-code-other-buffers (current-buffer))))
(not company-dabbrev-code-everywhere)))
:expire t
:check-tag
(cons regexp company-dabbrev-code-completion-styles))))
(defun company-dabbrev-code--filter (prefix suffix table)
(let ((completion-ignore-case company-dabbrev-code-ignore-case)
(completion-styles (if (listp company-dabbrev-code-completion-styles)
company-dabbrev-code-completion-styles
completion-styles))
(metadata (completion-metadata prefix table nil))
res)
(if (not company-dabbrev-code-completion-styles)
(all-completions prefix table)
(setq res (company--capf-completions
prefix suffix
table nil
metadata))
(when-let* ((sort-fn (completion-metadata-get metadata 'display-sort-function)))
(setq company-dabbrev-code--sorted t)
(setf (alist-get :completions res)
(funcall sort-fn (alist-get :completions res))))
(setq company-dabbrev--boundaries
(company--capf-boundaries-markers
(assoc-default :boundaries res)
company-dabbrev--boundaries))
(assoc-default :completions res))))
(provide 'company-dabbrev-code)
;;; company-dabbrev-code.el ends here