Create fix for Company-fuzzy bug
Apparently NOBODY on the interwebz seemed to have a bug like this, and so, nobody knew how to fix it. Related bugs in other projects and their general solutions also failed. So eventually I just tried a dirty hack and it works flawlessly again. I added the fixed file to the repo tracker and added a warning for future me so I never have to deal with this annoying shitstain ever again.
- Author
- Maarten Vangeneugden
- Date
- Sept. 15, 2024, 5:32 p.m.
- Hash
- 226ba1eacdfb635e5235eb8141724d5cb1ce2045
- Parent
- d8fd1df30e145c60dbe0ad775b5aca18398c064a
- Modified files
- company-fuzzy.el
- init.el
company-fuzzy.el ¶
876 additions and 0 deletions.
View changes Hide changes
+ |
1 |
|
+ |
2 |
;; Copyright (C) 2019-2024 Shen, Jen-Chieh |
+ |
3 |
;; Created date 2019-08-01 16:54:34 |
+ |
4 |
;; FIXED by Maarten Vangeneugden at 2024-09-15 |
+ |
5 |
|
+ |
6 |
;; Author: Shen, Jen-Chieh <jcs090218@gmail.com> |
+ |
7 |
;; URL: https://github.com/jcs-elpa/company-fuzzy |
+ |
8 |
;; Version: 1.4.0 |
+ |
9 |
;; Package-Requires: ((emacs "26.1") (company "0.8.12") (s "1.12.0") (ht "2.0")) |
+ |
10 |
;; Keywords: matching auto-complete complete fuzzy |
+ |
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 <https://www.gnu.org/licenses/>. |
+ |
26 |
|
+ |
27 |
;;; Commentary: |
+ |
28 |
;; |
+ |
29 |
;; Fuzzy matching for `company-mode'. |
+ |
30 |
;; |
+ |
31 |
|
+ |
32 |
;;; Code: |
+ |
33 |
|
+ |
34 |
(require 'cl-lib) |
+ |
35 |
(require 'ffap) |
+ |
36 |
(require 'subr-x) |
+ |
37 |
|
+ |
38 |
(require 'company) |
+ |
39 |
(require 'ht) |
+ |
40 |
(require 's) |
+ |
41 |
|
+ |
42 |
(defgroup company-fuzzy nil |
+ |
43 |
"Fuzzy matching for `company-mode'." |
+ |
44 |
:prefix "company-fuzzy-" |
+ |
45 |
:group 'company |
+ |
46 |
:link '(url-link :tag "Repository" "https://github.com/jcs-elpa/company-fuzzy")) |
+ |
47 |
|
+ |
48 |
(defcustom company-fuzzy-sorting-backend 'alphabetic |
+ |
49 |
"Type for sorting/scoring backend." |
+ |
50 |
:type '(choice (const :tag "none" none) |
+ |
51 |
(const :tag "alphabetic" alphabetic) |
+ |
52 |
(const :tag "flex" flex) |
+ |
53 |
(const :tag "flx" flx) |
+ |
54 |
(const :tag "flx-rs" flx-rs) |
+ |
55 |
(const :tag "flxy" flxy) |
+ |
56 |
(const :tag "fuz-skim" fuz-skim) |
+ |
57 |
(const :tag "fuz-clangd" fuz-clangd) |
+ |
58 |
(const :tag "fuz-bin-skim" fuz-bin-skim) |
+ |
59 |
(const :tag "fuz-bin-clangd" fuz-bin-clangd) |
+ |
60 |
(const :tag "liquidmetal" liquidmetal) |
+ |
61 |
(const :tag "sublime-fuzzy" sublime-fuzzy)) |
+ |
62 |
:group 'company-fuzzy) |
+ |
63 |
|
+ |
64 |
(defcustom company-fuzzy-prefix-on-top t |
+ |
65 |
"Have the matching prefix on top." |
+ |
66 |
:type 'boolean |
+ |
67 |
:group 'company-fuzzy) |
+ |
68 |
|
+ |
69 |
(defcustom company-fuzzy-sorting-function nil |
+ |
70 |
"Function that gives all candidates and let you do your own sorting." |
+ |
71 |
:type '(choice (const :tag "None" nil) |
+ |
72 |
function) |
+ |
73 |
:group 'company-fuzzy) |
+ |
74 |
|
+ |
75 |
(defcustom company-fuzzy-sorting-score-function nil |
+ |
76 |
"Function that gives candidates with same score and let you do your own sorting." |
+ |
77 |
:type '(choice (const :tag "None" nil) |
+ |
78 |
function) |
+ |
79 |
:group 'company-fuzzy) |
+ |
80 |
|
+ |
81 |
(defcustom company-fuzzy-show-annotation t |
+ |
82 |
"Show annotation from source." |
+ |
83 |
:type 'boolean |
+ |
84 |
:group 'company-fuzzy) |
+ |
85 |
|
+ |
86 |
(defcustom company-fuzzy-annotation-format " <%s>" |
+ |
87 |
"Annotation string format." |
+ |
88 |
:type 'string |
+ |
89 |
:group 'company-fuzzy) |
+ |
90 |
|
+ |
91 |
(defcustom company-fuzzy-passthrough-backends nil |
+ |
92 |
"List of backends that already are fuzzy, so no filtering of candidates is done." |
+ |
93 |
:type 'list |
+ |
94 |
:group 'company-fuzzy) |
+ |
95 |
|
+ |
96 |
(defcustom company-fuzzy-trigger-symbols '("." "->") |
+ |
97 |
"List of symbols that allow trigger company when there is no prefix." |
+ |
98 |
:type 'list |
+ |
99 |
:group 'company-fuzzy) |
+ |
100 |
|
+ |
101 |
(defcustom company-fuzzy-completion-separator "[ \t\r\n]\\|\\_<\\|\\_>" |
+ |
102 |
"Use to identify the completion unit." |
+ |
103 |
:type 'string |
+ |
104 |
:group 'company-fuzzy) |
+ |
105 |
|
+ |
106 |
(defcustom company-fuzzy-reset-selection nil |
+ |
107 |
"If non-nil, reset the selection to default." |
+ |
108 |
:type 'boolean |
+ |
109 |
:group 'company-fuzzy) |
+ |
110 |
|
+ |
111 |
(defface company-fuzzy-annotation-face |
+ |
112 |
'((t (:inherit company-tooltip-annotation))) |
+ |
113 |
"Face for annotation." |
+ |
114 |
:group 'company-fuzzy) |
+ |
115 |
|
+ |
116 |
(defvar-local company-fuzzy--prefix "" |
+ |
117 |
"Generic prefix.") |
+ |
118 |
|
+ |
119 |
(defvar-local company-fuzzy--prefix-first "" |
+ |
120 |
"Store generic prefix's first character for caching.") |
+ |
121 |
|
+ |
122 |
(defvar-local company-fuzzy--backends nil |
+ |
123 |
"Company fuzzy backends we are going to use.") |
+ |
124 |
|
+ |
125 |
(defvar-local company-fuzzy--recorded-backends nil |
+ |
126 |
"Record down company local backends in current buffer.") |
+ |
127 |
|
+ |
128 |
(defvar-local company-fuzzy--is-trigger-prefix-p nil |
+ |
129 |
"Flag to see if currently completion having a valid prefix.") |
+ |
130 |
|
+ |
131 |
(defvar-local company-fuzzy--prefixes (make-hash-table :test 'equal) |
+ |
132 |
"Map for each backend's prefix.") |
+ |
133 |
|
+ |
134 |
(defvar-local company-fuzzy--candidates (make-hash-table :test 'equal) |
+ |
135 |
"Map for each bakend's candidates.") |
+ |
136 |
|
+ |
137 |
;; |
+ |
138 |
;; (@* "External" ) |
+ |
139 |
;; |
+ |
140 |
|
+ |
141 |
(declare-function flex-score "ext:flex.el") |
+ |
142 |
(declare-function flx-score "ext:flx.el") |
+ |
143 |
(declare-function flx-rs-score "ext:flx-rs.el") |
+ |
144 |
(declare-function flx-rs-load-dyn "ext:flx-rs.el") |
+ |
145 |
|
+ |
146 |
(declare-function flxy-score "ext:flxy.el") |
+ |
147 |
(declare-function flxy-load-dyn "ext:flxy.el") |
+ |
148 |
|
+ |
149 |
(declare-function fuz-calc-score-skim "ext:fuz.el") |
+ |
150 |
(declare-function fuz-calc-score-clangd "ext:fuz.el") |
+ |
151 |
(declare-function fuz-build-and-load-dymod "ext:fuz.el") |
+ |
152 |
|
+ |
153 |
(declare-function fuz-bin-score-skim "ext:fuz-bin.el") |
+ |
154 |
(declare-function fuz-bin-score-clangd "ext:fuz-bin.el") |
+ |
155 |
(declare-function fuz-bin-load-dyn "ext:fuz-bin.el") |
+ |
156 |
|
+ |
157 |
(declare-function liquidmetal-score "ext:liquidmetal.el") |
+ |
158 |
|
+ |
159 |
(declare-function sublime-fuzzy-score "ext:sublime-fuzzy.el") |
+ |
160 |
(declare-function sublime-fuzzy-load-dyn "ext:sublime-fuzzy.el") |
+ |
161 |
|
+ |
162 |
(declare-function company-emmet--prefix "ext:company-emmet.el") |
+ |
163 |
|
+ |
164 |
;; |
+ |
165 |
;; (@* "Mode" ) |
+ |
166 |
;; |
+ |
167 |
|
+ |
168 |
(defun company-fuzzy--init () |
+ |
169 |
"Initialize all sorting backends." |
+ |
170 |
(cl-case company-fuzzy-sorting-backend |
+ |
171 |
(`flex (require 'flex)) |
+ |
172 |
(`flx (require 'flx)) |
+ |
173 |
(`flx-rs (require 'flx-rs) (flx-rs-load-dyn)) |
+ |
174 |
(`flxy (require 'flxy) (flxy-load-dyn)) |
+ |
175 |
((or fuz-skim fuz-clangd) |
+ |
176 |
(require 'fuz) |
+ |
177 |
(unless (require 'fuz-core nil t) (fuz-build-and-load-dymod))) |
+ |
178 |
((or fuz-bin-skim fuz-bin-clangd) |
+ |
179 |
(require 'fuz-bin) (fuz-bin-load-dyn)) |
+ |
180 |
(`liquidmetal (require 'liquidmetal)) |
+ |
181 |
(`sublime-fuzzy (require 'sublime-fuzzy) (sublime-fuzzy-load-dyn)))) |
+ |
182 |
|
+ |
183 |
(defun company-fuzzy--enable () |
+ |
184 |
"Record down all other backend to `company-fuzzy--backends'." |
+ |
185 |
(company-fuzzy--init) |
+ |
186 |
;; XXX Don't know why, but you need to clear it first to make local |
+ |
187 |
;; variables work! |
+ |
188 |
(ht-clear company-fuzzy--prefixes) |
+ |
189 |
(ht-clear company-fuzzy--candidates) |
+ |
190 |
(unless company-fuzzy--recorded-backends |
+ |
191 |
(setq company-fuzzy--recorded-backends company-backends |
+ |
192 |
company-fuzzy--backends (company-fuzzy--normalize-backend-list company-fuzzy--recorded-backends)) |
+ |
193 |
(setq-local company-backends '(company-fuzzy-all-other-backends)) |
+ |
194 |
(setq-local company-transformers (append company-transformers '(company-fuzzy--sort-candidates))) |
+ |
195 |
(advice-add 'company--insert-candidate :before #'company-fuzzy--insert-candidate) |
+ |
196 |
(advice-add 'company-yasnippet--completions-for-prefix :around #'company-fuzzy-yasnippet--completions-for-prefix)) |
+ |
197 |
(add-hook 'lsp-completion-mode-hook #'company-fuzzy--lsp-after-enabled nil t) |
+ |
198 |
(add-hook 'eglot-managed-mode-hook #'company-fuzzy--lsp-after-enabled nil t)) |
+ |
199 |
|
+ |
200 |
(defun company-fuzzy--disable () |
+ |
201 |
"Revert all other backend back to `company-backends'." |
+ |
202 |
(when company-fuzzy--recorded-backends |
+ |
203 |
(setq-local company-backends company-fuzzy--recorded-backends) |
+ |
204 |
(setq-local company-transformers (delq 'company-fuzzy--sort-candidates company-transformers)) |
+ |
205 |
(setq company-fuzzy--recorded-backends nil |
+ |
206 |
company-fuzzy--backends nil) |
+ |
207 |
(advice-remove 'company--insert-candidate #'company-fuzzy--insert-candidate) |
+ |
208 |
(advice-remove 'company-yasnippet--completions-for-prefix #'company-fuzzy-yasnippet--completions-for-prefix)) |
+ |
209 |
(remove-hook 'lsp-completion-mode-hook #'company-fuzzy--lsp-after-enabled t) |
+ |
210 |
(remove-hook 'eglot-managed-mode-hook #'company-fuzzy--lsp-after-enabled t)) |
+ |
211 |
|
+ |
212 |
;;;###autoload |
+ |
213 |
(define-minor-mode company-fuzzy-mode |
+ |
214 |
"Minor mode `company-fuzzy-mode'." |
+ |
215 |
:lighter " ComFuz" |
+ |
216 |
:group company-fuzzy |
+ |
217 |
(if company-fuzzy-mode (company-fuzzy--enable) (company-fuzzy--disable))) |
+ |
218 |
|
+ |
219 |
(defun company-fuzzy-turn-on-company-fuzzy-mode () |
+ |
220 |
"Turn on the `company-fuzzy-mode'." |
+ |
221 |
(company-fuzzy-mode 1)) |
+ |
222 |
|
+ |
223 |
;;;###autoload |
+ |
224 |
(define-globalized-minor-mode global-company-fuzzy-mode |
+ |
225 |
company-fuzzy-mode company-fuzzy-turn-on-company-fuzzy-mode |
+ |
226 |
:group 'company-fuzzy |
+ |
227 |
:require 'company-fuzzy) |
+ |
228 |
|
+ |
229 |
;; |
+ |
230 |
;; (@* "Utilies" ) |
+ |
231 |
;; |
+ |
232 |
|
+ |
233 |
(defun company-fuzzy--valid-candidates-p (candidates) |
+ |
234 |
"Return non-nil if CANDIDATES is list of valid candidates." |
+ |
235 |
(ignore-errors (stringp (nth 0 candidates)))) |
+ |
236 |
|
+ |
237 |
(defun company-fuzzy--async-candidates-p (candidates) |
+ |
238 |
"Return non-nil if CANDIDATES is in async format." |
+ |
239 |
(when (consp candidates) |
+ |
240 |
(and (eq (car candidates) :async) (functionp (cdr candidates))))) |
+ |
241 |
|
+ |
242 |
(defun company-fuzzy--symbol-start () |
+ |
243 |
"Return symbol start point from current cursor position." |
+ |
244 |
(ignore-errors |
+ |
245 |
(save-excursion |
+ |
246 |
(forward-char -1) |
+ |
247 |
(re-search-backward company-fuzzy-completion-separator) |
+ |
248 |
(point)))) |
+ |
249 |
|
+ |
250 |
(defun company-fuzzy--furthest-prefix () |
+ |
251 |
"Return the possible furthest (greatest length) prefix." |
+ |
252 |
(ht-clear company-fuzzy--prefixes) |
+ |
253 |
(let ((final-len 0) final-prefix) |
+ |
254 |
(dolist (backend company-fuzzy--backends) |
+ |
255 |
(when-let ((prefix (ignore-errors (funcall backend 'prefix)))) |
+ |
256 |
(ht-set company-fuzzy--prefixes backend prefix) |
+ |
257 |
(when-let* ((len (length prefix)) |
+ |
258 |
((< final-len len))) |
+ |
259 |
(setq final-prefix prefix |
+ |
260 |
final-len len)))) |
+ |
261 |
final-prefix)) |
+ |
262 |
|
+ |
263 |
(defun company-fuzzy--generic-prefix () |
+ |
264 |
"Return the most generic prefix." |
+ |
265 |
(let ((start (company-fuzzy--symbol-start))) |
+ |
266 |
(ignore-errors |
+ |
267 |
(string-trim (buffer-substring-no-properties (or start (point-min)) (point)))))) |
+ |
268 |
|
+ |
269 |
(defun company-fuzzy--trigger-prefix-p () |
+ |
270 |
"Check if current prefix a trigger prefix." |
+ |
271 |
(member company-fuzzy--prefix company-fuzzy-trigger-symbols)) |
+ |
272 |
|
+ |
273 |
(defun company-fuzzy--string-match (regexp string &optional start) |
+ |
274 |
"Safe way to execute function `string-match'. |
+ |
275 |
See function `string-match' for arguments REGEXP, STRING and START." |
+ |
276 |
(or (ignore-errors (string-match regexp string start)) |
+ |
277 |
(ignore-errors (string-match (regexp-quote regexp) string start)))) |
+ |
278 |
|
+ |
279 |
(defun company-fuzzy--string-match-p (regexp string &optional start) |
+ |
280 |
"Safe way to execute function `string-match-p'. |
+ |
281 |
See function `string-match-p' for arguments REGEXP, STRING and START." |
+ |
282 |
(or (ignore-errors (string-match-p regexp string start)) |
+ |
283 |
(ignore-errors (string-match-p (regexp-quote regexp) string start)))) |
+ |
284 |
|
+ |
285 |
(defun company-fuzzy--string-prefix-p (prefix string &optional ignore-case) |
+ |
286 |
"Safe way to execute function `string-prefix-p'. |
+ |
287 |
See function `string-prefix-p' for arguments PREFIX, STRING and IGNORE-CASE." |
+ |
288 |
(ignore-errors (string-prefix-p prefix string ignore-case))) |
+ |
289 |
|
+ |
290 |
(defun company-fuzzy--normalize-backend-list (backends) |
+ |
291 |
"Normalize all BACKENDS as list." |
+ |
292 |
(let (result-lst) |
+ |
293 |
(dolist (backend backends) |
+ |
294 |
(if (listp backend) |
+ |
295 |
(let ((index 0)) |
+ |
296 |
(dolist (back backend) |
+ |
297 |
(when (company-fuzzy--string-prefix-p "company-" (symbol-name back)) |
+ |
298 |
(push (nth index backend) result-lst)) |
+ |
299 |
(setq index (1+ index)))) |
+ |
300 |
(push backend result-lst))) |
+ |
301 |
(setq result-lst (reverse result-lst)) |
+ |
302 |
(cl-remove-duplicates result-lst))) |
+ |
303 |
|
+ |
304 |
(defun company-fuzzy--get-backend-by-candidate (candidate) |
+ |
305 |
"Return the backend symbol by using CANDIDATE as search index." |
+ |
306 |
(let ((match (ht-find (lambda (_backend cands) |
+ |
307 |
(member candidate cands)) |
+ |
308 |
company-fuzzy--candidates))) |
+ |
309 |
(car match))) |
+ |
310 |
|
+ |
311 |
(defun company-fuzzy--call-backend (backend command key) |
+ |
312 |
"Safely call BACKEND by COMMAND and KEY." |
+ |
313 |
(ignore-errors (funcall backend command key))) |
+ |
314 |
|
+ |
315 |
(defun company-fuzzy--backend-command (candidate command) |
+ |
316 |
"Find the backend from the CANDIDATE then call the COMMAND." |
+ |
317 |
(unless (string-empty-p candidate) |
+ |
318 |
(when-let ((backend (company-fuzzy--get-backend-by-candidate candidate))) |
+ |
319 |
(company-fuzzy--call-backend backend command candidate)))) |
+ |
320 |
|
+ |
321 |
;; |
+ |
322 |
;; (@* "Annotation" ) |
+ |
323 |
;; |
+ |
324 |
|
+ |
325 |
(defun company-fuzzy--get-backend-string (backend) |
+ |
326 |
"Get BACKEND's as a string." |
+ |
327 |
(if backend |
+ |
328 |
(let ((name (symbol-name backend))) |
+ |
329 |
(setq name (s-replace "company-" "" name) |
+ |
330 |
name (s-replace "-company" "" name)) |
+ |
331 |
name) |
+ |
332 |
"")) |
+ |
333 |
|
+ |
334 |
(defun company-fuzzy--backend-string (candidate backend) |
+ |
335 |
"Form the BACKEND string by CANDIDATE." |
+ |
336 |
(if (and company-fuzzy-show-annotation candidate) |
+ |
337 |
(let ((backend-str (company-fuzzy--get-backend-string backend))) |
+ |
338 |
(when (string-empty-p backend-str) (setq backend-str "unknown")) |
+ |
339 |
(propertize |
+ |
340 |
(format company-fuzzy-annotation-format backend-str) |
+ |
341 |
'face 'company-fuzzy-annotation-face)) |
+ |
342 |
"")) |
+ |
343 |
|
+ |
344 |
(defun company-fuzzy--source-anno-string (candidate backend) |
+ |
345 |
"Return the source annotation string by CANDIDATE and BACKEND." |
+ |
346 |
(if (and candidate backend) |
+ |
347 |
(company-fuzzy--call-backend backend 'annotation candidate) |
+ |
348 |
"")) |
+ |
349 |
|
+ |
350 |
(defun company-fuzzy--extract-annotation (candidate) |
+ |
351 |
"Extract annotation from CANDIDATE." |
+ |
352 |
(let* ((backend (company-fuzzy--get-backend-by-candidate candidate)) |
+ |
353 |
(backend-str (company-fuzzy--backend-string candidate backend)) |
+ |
354 |
(orig-anno (company-fuzzy--source-anno-string candidate backend))) |
+ |
355 |
(concat orig-anno backend-str))) |
+ |
356 |
|
+ |
357 |
;; |
+ |
358 |
;; (@* "Highlighting" ) |
+ |
359 |
;; |
+ |
360 |
|
+ |
361 |
(defun company-fuzzy--pre-render (str &optional annotation-p) |
+ |
362 |
"Prerender color with STR and flag ANNOTATION-P." |
+ |
363 |
(unless annotation-p |
+ |
364 |
(let* ((str-len (length str)) |
+ |
365 |
(prefix (company-fuzzy--backend-prefix-candidate str 'match)) |
+ |
366 |
(prefix (company-fuzzy--validate-prefix prefix)) |
+ |
367 |
(selection (or company-selection 0)) |
+ |
368 |
(cur-selection (nth selection company-candidates)) |
+ |
369 |
(splitted-section (remove "" (split-string str " "))) |
+ |
370 |
(process-selection (nth 0 splitted-section)) |
+ |
371 |
(selected (string= cur-selection process-selection)) |
+ |
372 |
(selected-face (if selected |
+ |
373 |
'company-tooltip-common-selection |
+ |
374 |
'company-tooltip-common)) |
+ |
375 |
(selected-common-face (if selected |
+ |
376 |
'company-tooltip-selection |
+ |
377 |
'company-tooltip)) |
+ |
378 |
(splitted-c (remove "" (split-string prefix "")))) |
+ |
379 |
(set-text-properties 0 str-len nil str) |
+ |
380 |
(font-lock-prepend-text-property 0 str-len 'face selected-common-face str) |
+ |
381 |
(dolist (c splitted-c) |
+ |
382 |
(let ((pos (company-fuzzy--string-match-p (regexp-quote c) str))) |
+ |
383 |
(while (and (numberp pos) (< pos str-len)) |
+ |
384 |
(font-lock-prepend-text-property pos (1+ pos) 'face selected-face str) |
+ |
385 |
(setq pos (company-fuzzy--string-match-p (regexp-quote c) str (1+ pos)))))))) |
+ |
386 |
str) |
+ |
387 |
|
+ |
388 |
;; |
+ |
389 |
;; (@* "Sorting / Scoring" ) |
+ |
390 |
;; |
+ |
391 |
|
+ |
392 |
(defun company-fuzzy--sort-prefix-on-top (candidates) |
+ |
393 |
"Sort CANDIDATES that match prefix on top of all other selection." |
+ |
394 |
(let (prefix-matches prefix) |
+ |
395 |
(dolist (cand candidates) |
+ |
396 |
(setq prefix (company-fuzzy--backend-prefix-candidate cand 'match) |
+ |
397 |
prefix (company-fuzzy--validate-prefix prefix)) |
+ |
398 |
(when (company-fuzzy--string-prefix-p prefix cand) |
+ |
399 |
(push cand prefix-matches) |
+ |
400 |
(setq candidates (remove cand candidates)))) |
+ |
401 |
(setq prefix-matches (sort prefix-matches #'string-lessp) |
+ |
402 |
candidates (append prefix-matches candidates))) |
+ |
403 |
candidates) |
+ |
404 |
|
+ |
405 |
(defun company-fuzzy--sort-candidates-by-function (candidates fnc &optional flip) |
+ |
406 |
"Sort CANDIDATES with function call FNC. |
+ |
407 |
|
+ |
408 |
If optional argument FLIP is non-nil, reverse query and pattern order." |
+ |
409 |
(let ((scoring-table (make-hash-table :test 'equal)) scoring-keys) |
+ |
410 |
(dolist (cand candidates) |
+ |
411 |
(when-let* ((prefix (company-fuzzy--backend-prefix-candidate cand 'match)) |
+ |
412 |
(scoring (or (equal prefix 'anything) |
+ |
413 |
(ignore-errors |
+ |
414 |
(if flip (funcall fnc prefix cand) |
+ |
415 |
(funcall fnc cand prefix))))) |
+ |
416 |
(score (cond ((listp scoring) (nth 0 scoring)) |
+ |
417 |
((vectorp scoring) (aref scoring 0)) |
+ |
418 |
((numberp scoring) scoring) |
+ |
419 |
(t 0)))) |
+ |
420 |
(ht-set scoring-table score (push cand (ht-get scoring-table score))))) |
+ |
421 |
;; Get all keys, and turn into a list. |
+ |
422 |
(ht-map (lambda (score-key _cands) (push score-key scoring-keys)) scoring-table) |
+ |
423 |
(setq scoring-keys (sort scoring-keys #'>) ; Sort keys in order. |
+ |
424 |
candidates nil) ; Clean up, and ready for final output. |
+ |
425 |
(dolist (key scoring-keys) |
+ |
426 |
(let ((cands (ht-get scoring-table key))) |
+ |
427 |
(setq cands (reverse cands)) ; Respect to backend order. |
+ |
428 |
(when (functionp company-fuzzy-sorting-score-function) |
+ |
429 |
(setq cands (funcall company-fuzzy-sorting-score-function cands))) |
+ |
430 |
(setq candidates (append candidates cands))))) |
+ |
431 |
candidates) |
+ |
432 |
|
+ |
433 |
(defun company-fuzzy--sort-candidates (candidates) |
+ |
434 |
"Sort all CANDIDATES base on type of sorting backend." |
+ |
435 |
;; IMPORTANT: Since the command `candidates' will change by `company-mode', |
+ |
436 |
;; we manually set the candidates here so we get can consistent result. |
+ |
437 |
(setq candidates (company-fuzzy--ht-all-candidates)) |
+ |
438 |
(when company-fuzzy-reset-selection |
+ |
439 |
(setq company-selection company-selection-default)) |
+ |
440 |
;; Don't score when it start fresh, e.g. completing a function name in Java |
+ |
441 |
;; with the . (dot) symbol |
+ |
442 |
(unless company-fuzzy--is-trigger-prefix-p |
+ |
443 |
(setq candidates |
+ |
444 |
(cl-case company-fuzzy-sorting-backend |
+ |
445 |
(`none candidates) |
+ |
446 |
(`alphabetic (sort candidates #'string-lessp)) |
+ |
447 |
(`flex |
+ |
448 |
(company-fuzzy--sort-candidates-by-function candidates #'flex-score)) |
+ |
449 |
(`flx |
+ |
450 |
(company-fuzzy--sort-candidates-by-function candidates #'flx-score)) |
+ |
451 |
(`flx-rs |
+ |
452 |
(company-fuzzy--sort-candidates-by-function candidates #'flx-rs-score)) |
+ |
453 |
(`flxy |
+ |
454 |
(company-fuzzy--sort-candidates-by-function candidates #'flxy-score)) |
+ |
455 |
((or fuz-skim fuz-clangd) |
+ |
456 |
(company-fuzzy--sort-candidates-by-function |
+ |
457 |
candidates (if (eq company-fuzzy-sorting-backend 'fuz-skim) |
+ |
458 |
#'fuz-calc-score-skim |
+ |
459 |
#'fuz-calc-score-clangd) |
+ |
460 |
t)) |
+ |
461 |
((or fuz-bin-skim fuz-bin-clangd) |
+ |
462 |
(company-fuzzy--sort-candidates-by-function |
+ |
463 |
candidates (if (eq company-fuzzy-sorting-backend 'fuz-bin-skim) |
+ |
464 |
'fuz-bin-score-skim |
+ |
465 |
'fuz-bin-score-clangd) |
+ |
466 |
t)) |
+ |
467 |
(`liquidmetal |
+ |
468 |
(company-fuzzy--sort-candidates-by-function candidates #'liquidmetal-score)) |
+ |
469 |
(`sublime-fuzzy |
+ |
470 |
(company-fuzzy--sort-candidates-by-function candidates #'sublime-fuzzy-score t)))) |
+ |
471 |
(when company-fuzzy-prefix-on-top |
+ |
472 |
(setq candidates (company-fuzzy--sort-prefix-on-top candidates))) |
+ |
473 |
(when (functionp company-fuzzy-sorting-function) |
+ |
474 |
(setq candidates (funcall company-fuzzy-sorting-function candidates)))) |
+ |
475 |
candidates) |
+ |
476 |
|
+ |
477 |
;; |
+ |
478 |
;; (@* "Completion" ) |
+ |
479 |
;; |
+ |
480 |
|
+ |
481 |
;; ZEG WEET GE WAAROM IK DIE tfuuiyf HEB TOEGEVOEGD?? |
+ |
482 |
;; OMDAT DEZE KAKFUNCTIE DAN INEENS GEFIKST IS WAUW |
+ |
483 |
(defun company-fuzzy--insert-candidate (candidate tfuuiyf) |
+ |
484 |
"Insertion for CANDIDATE." |
+ |
485 |
(when company-fuzzy-mode |
+ |
486 |
;; NOTE: Here we force to change `company-prefix' so the completion |
+ |
487 |
;; will do what we expected. |
+ |
488 |
(let ((backend (company-fuzzy--get-backend-by-candidate candidate))) |
+ |
489 |
(setq company-prefix (company-fuzzy--backend-prefix backend 'complete))))) |
+ |
490 |
|
+ |
491 |
;; |
+ |
492 |
;; (@* "Prefix" ) |
+ |
493 |
;; |
+ |
494 |
|
+ |
495 |
(defun company-fuzzy--valid-prefix (backend) |
+ |
496 |
"Guess the current BACKEND prefix." |
+ |
497 |
(let ((prefix (ht-get company-fuzzy--prefixes backend))) |
+ |
498 |
(if (stringp prefix) prefix |
+ |
499 |
(thing-at-point 'symbol)))) ; Fallback |
+ |
500 |
|
+ |
501 |
(defun company-fuzzy--validate-prefix (prefix) |
+ |
502 |
"Validate the PREFIX to proper string." |
+ |
503 |
(if (stringp prefix) ; this will handle 'anything symbol type |
+ |
504 |
prefix "")) |
+ |
505 |
|
+ |
506 |
(defun company-fuzzy--backend-prefix-complete (backend) |
+ |
507 |
"Return prefix for each BACKEND while doing completion. |
+ |
508 |
|
+ |
509 |
This function is use when function `company-fuzzy--insert-candidate' is |
+ |
510 |
called. It returns the current selection prefix to prevent completion |
+ |
511 |
completes in an odd way." |
+ |
512 |
(cl-case backend |
+ |
513 |
(`company-paths (company-fuzzy--valid-prefix backend)) |
+ |
514 |
(t (company-fuzzy--backend-prefix backend 'filter)))) |
+ |
515 |
|
+ |
516 |
(defun company-fuzzy--backend-prefix-filter (backend) |
+ |
517 |
"Return prefix for each BACKEND while doing the first basic filerting. |
+ |
518 |
|
+ |
519 |
This is some what the opposite to function `company-fuzzy--backend-prefix-get' |
+ |
520 |
since it's try get as much candidates as possible, but this function returns |
+ |
521 |
a prefix that can filter out some obvious impossible candidates." |
+ |
522 |
(cl-case backend |
+ |
523 |
(`company-capf (let* ((prefix (company-fuzzy--backend-prefix backend 'match)) |
+ |
524 |
(prefix (company-fuzzy--validate-prefix prefix))) |
+ |
525 |
prefix)) |
+ |
526 |
(`company-files (company-fuzzy--valid-prefix backend)) |
+ |
527 |
(`company-paths (company-fuzzy--backend-prefix 'company-files 'match)) |
+ |
528 |
(t (company-fuzzy--backend-prefix backend 'match)))) |
+ |
529 |
|
+ |
530 |
(defun company-fuzzy--backend-prefix-match (backend) |
+ |
531 |
"Return prefix for each BACKEND while matching candidates. |
+ |
532 |
|
+ |
533 |
This function is use for scoring and matching algorithm. It returns a prefix |
+ |
534 |
that best describe the current possible candidate. |
+ |
535 |
|
+ |
536 |
For instance, if there is a candidate function `buffer-file-name' and with |
+ |
537 |
current prefix `bfn'. It will just return `bfn' because the current prefix |
+ |
538 |
does best describe the for this candidate." |
+ |
539 |
(cl-case backend |
+ |
540 |
((company-capf) (or (company-fuzzy--valid-prefix backend) |
+ |
541 |
'anything)) |
+ |
542 |
(`company-c-headers |
+ |
543 |
(when-let ((prefix (ht-get company-fuzzy--prefixes backend))) |
+ |
544 |
;; Skip the first < or " symbol |
+ |
545 |
(substring prefix 1 (length prefix)))) |
+ |
546 |
(`company-files |
+ |
547 |
;; NOTE: For `company-files', we will return the last section of the path |
+ |
548 |
;; for the best match. |
+ |
549 |
;; |
+ |
550 |
;; Example, if I have path `/path/to/dir'; then it shall return `dir'. |
+ |
551 |
(when-let* ((prefix (ht-get company-fuzzy--prefixes backend)) |
+ |
552 |
(splitted (split-string prefix "/" t)) |
+ |
553 |
(len-splitted (length splitted)) |
+ |
554 |
(last (nth (1- len-splitted) splitted))) |
+ |
555 |
last)) |
+ |
556 |
(`company-paths |
+ |
557 |
(when-let ((prefix (ht-get company-fuzzy--prefixes backend))) |
+ |
558 |
(if (string-suffix-p "/" prefix) 'anything |
+ |
559 |
(nth 0 (last (split-string prefix "/" t)))))) |
+ |
560 |
(t company-fuzzy--prefix))) |
+ |
561 |
|
+ |
562 |
(defun company-fuzzy--backend-prefix-get (backend) |
+ |
563 |
"Return prefix for each BACKEND while getting candidates. |
+ |
564 |
|
+ |
565 |
This function is use for simplify prefix, in order to get as much candidates |
+ |
566 |
as possible for fuzzy work. |
+ |
567 |
|
+ |
568 |
For instance, if I have prefix `bfn'; then most BACKEND will not return |
+ |
569 |
function `buffer-file-name' as candidate. But with this function will use a |
+ |
570 |
letter `b' instead of full prefix `bfn'. So the BACKEND will return something |
+ |
571 |
that may be relavent to the first character `b'. |
+ |
572 |
|
+ |
573 |
P.S. Not all backend work this way." |
+ |
574 |
(cl-case backend |
+ |
575 |
(`company-c-headers |
+ |
576 |
;; Skip the < or " symbol for the first character |
+ |
577 |
(ignore-errors (substring (ht-get company-fuzzy--prefixes backend) 1 2))) |
+ |
578 |
(`company-files |
+ |
579 |
(when-let ((prefix (ht-get company-fuzzy--prefixes backend))) |
+ |
580 |
(let* ((splitted (split-string prefix "/" t)) |
+ |
581 |
(len-splitted (length splitted)) |
+ |
582 |
(last (nth (1- len-splitted) splitted)) |
+ |
583 |
(new-prefix prefix)) |
+ |
584 |
(when (< 1 len-splitted) |
+ |
585 |
(setq new-prefix |
+ |
586 |
(substring prefix 0 (- (length prefix) (length last))))) |
+ |
587 |
new-prefix))) |
+ |
588 |
(`company-paths |
+ |
589 |
(when-let ((prefix (ht-get company-fuzzy--prefixes backend))) |
+ |
590 |
(if (string-suffix-p "/" prefix) prefix |
+ |
591 |
(file-name-directory prefix)))) |
+ |
592 |
(`company-emmet (company-emmet--prefix)) |
+ |
593 |
(t |
+ |
594 |
;; Return an empty string or first character is likely going to return a |
+ |
595 |
;; full list of candaidates. And this is what we want. |
+ |
596 |
(when (ht-get company-fuzzy--prefixes backend) |
+ |
597 |
company-fuzzy--prefix-first)))) |
+ |
598 |
|
+ |
599 |
(defun company-fuzzy--backend-prefix-candidate (cand type) |
+ |
600 |
"Get the backend prefix by CAND and TYPE." |
+ |
601 |
(let ((backend (company-fuzzy--get-backend-by-candidate cand))) |
+ |
602 |
(company-fuzzy--backend-prefix backend type))) |
+ |
603 |
|
+ |
604 |
(defun company-fuzzy--backend-prefix (backend type) |
+ |
605 |
"Get the BACKEND prefix by TYPE." |
+ |
606 |
(cl-case type |
+ |
607 |
(`complete (company-fuzzy--backend-prefix-complete backend)) |
+ |
608 |
(`filter (company-fuzzy--backend-prefix-filter backend)) |
+ |
609 |
(`match (company-fuzzy--backend-prefix-match backend)) |
+ |
610 |
(`get (company-fuzzy--backend-prefix-get backend)))) |
+ |
611 |
|
+ |
612 |
;; |
+ |
613 |
;; (@* "Fuzzy Matching" ) |
+ |
614 |
;; |
+ |
615 |
|
+ |
616 |
(defun company-fuzzy--trim-trailing-re (regex) |
+ |
617 |
"Trim incomplete REGEX. |
+ |
618 |
If REGEX ends with \\|, trim it, since then it matches an empty string." |
+ |
619 |
(if (company-fuzzy--string-match "\\`\\(.*\\)[\\]|\\'" regex) (match-string 1 regex) regex)) |
+ |
620 |
|
+ |
621 |
(defun company-fuzzy--regex-fuzzy (str) |
+ |
622 |
"Build a regex sequence from STR. |
+ |
623 |
Insert .* between each char." |
+ |
624 |
(setq str (company-fuzzy--trim-trailing-re str)) |
+ |
625 |
(if (company-fuzzy--string-match "\\`\\(\\^?\\)\\(.*?\\)\\(\\$?\\)\\'" str) |
+ |
626 |
(concat (match-string 1 str) |
+ |
627 |
(let ((lst (string-to-list (match-string 2 str)))) |
+ |
628 |
(apply #'concat |
+ |
629 |
(cl-mapcar |
+ |
630 |
#'concat |
+ |
631 |
(cons "" (cdr (mapcar (lambda (c) (format "[^%c\n]*" c)) |
+ |
632 |
lst))) |
+ |
633 |
(mapcar (lambda (x) (format "\\(%s\\)" (regexp-quote (char-to-string x)))) |
+ |
634 |
lst)))) |
+ |
635 |
(match-string 3 str)) |
+ |
636 |
str)) |
+ |
637 |
|
+ |
638 |
(defun company-fuzzy--match-string (prefix candidates) |
+ |
639 |
"Return new CANDIDATES that match PREFIX." |
+ |
640 |
(when (stringp prefix) |
+ |
641 |
(let ((fuz-str (company-fuzzy--regex-fuzzy prefix)) new-cands) |
+ |
642 |
(dolist (cand candidates) |
+ |
643 |
(when (company-fuzzy--string-match-p fuz-str cand) |
+ |
644 |
(push cand new-cands))) |
+ |
645 |
new-cands))) |
+ |
646 |
|
+ |
647 |
;; |
+ |
648 |
;; (@* "Core" ) |
+ |
649 |
;; |
+ |
650 |
|
+ |
651 |
(defun company-fuzzy--ht-all-candidates () |
+ |
652 |
"Return all candidates from the data." |
+ |
653 |
(let (all-candidates) |
+ |
654 |
(ht-map (lambda (_backend cands) |
+ |
655 |
(setq all-candidates (append all-candidates cands))) |
+ |
656 |
company-fuzzy--candidates) |
+ |
657 |
(delete-dups all-candidates))) |
+ |
658 |
|
+ |
659 |
(defun company-fuzzy-all-candidates () |
+ |
660 |
"Return the list of all candidates." |
+ |
661 |
(ht-clear company-fuzzy--candidates) ; Clean up |
+ |
662 |
(setq company-fuzzy--is-trigger-prefix-p (company-fuzzy--trigger-prefix-p)) |
+ |
663 |
(dolist (backend company-fuzzy--backends) |
+ |
664 |
(if (or (company-fuzzy--lsp-passthrough backend) |
+ |
665 |
(memq backend company-fuzzy-passthrough-backends)) |
+ |
666 |
(company-fuzzy--candidates-from-passthrough-backend backend) |
+ |
667 |
(company-fuzzy--candidates-from-backend backend))) |
+ |
668 |
;; Since we insert the candidates before sorting event, see function |
+ |
669 |
;; `company-fuzzy--sort-candidates', we return to simply avoid the process |
+ |
670 |
;; from `company-mode'. |
+ |
671 |
;; |
+ |
672 |
;; This should help us save some performance! |
+ |
673 |
(when (eq this-command 'company-diag) |
+ |
674 |
;; We did return candidates here, yet this does not mean `company-diag' |
+ |
675 |
;; will respect this result. |
+ |
676 |
(company-fuzzy--ht-all-candidates))) |
+ |
677 |
|
+ |
678 |
(defun company-fuzzy--candidates-from-passthrough-backend (backend) |
+ |
679 |
"Use candidates of already fuzzy BACKEND as is." |
+ |
680 |
(let ((prefix-get (company-fuzzy--backend-prefix backend 'get)) |
+ |
681 |
temp-candidates) |
+ |
682 |
(when prefix-get |
+ |
683 |
(setq temp-candidates (company-fuzzy--call-backend backend 'candidates prefix-get))) |
+ |
684 |
(company-fuzzy--collect-candidates backend temp-candidates))) |
+ |
685 |
|
+ |
686 |
(defun company-fuzzy--candidates-from-backend (backend) |
+ |
687 |
"Do fuzzy matching for current BACKEND." |
+ |
688 |
(let ((prefix-get (company-fuzzy--backend-prefix backend 'get)) |
+ |
689 |
(prefix-fil (company-fuzzy--backend-prefix backend 'filter)) |
+ |
690 |
temp-candidates) |
+ |
691 |
(when prefix-get |
+ |
692 |
(setq temp-candidates (company-fuzzy--call-backend backend 'candidates prefix-get))) |
+ |
693 |
;; NOTE: Do the very basic filtering for speed up. |
+ |
694 |
;; |
+ |
695 |
;; The function `company-fuzzy--match-string' does the very first basic |
+ |
696 |
;; filtering in order to lower the performance before sending to function |
+ |
697 |
;; scoring engine. |
+ |
698 |
(when (and (not company-fuzzy--is-trigger-prefix-p) |
+ |
699 |
(company-fuzzy--valid-candidates-p temp-candidates) |
+ |
700 |
prefix-fil) |
+ |
701 |
(setq temp-candidates (company-fuzzy--match-string prefix-fil temp-candidates))) |
+ |
702 |
;; NOTE: Made the final completion. |
+ |
703 |
(company-fuzzy--collect-candidates backend temp-candidates))) |
+ |
704 |
|
+ |
705 |
(defun company-fuzzy--register-candidates (backend candidates) |
+ |
706 |
"Register CANDIDATES with BACKEND id." |
+ |
707 |
(delete-dups candidates) |
+ |
708 |
(ht-set company-fuzzy--candidates backend (copy-sequence candidates))) |
+ |
709 |
|
+ |
710 |
(defun company-fuzzy--collect-candidates (backend candidates) |
+ |
711 |
"Collect BACKEND's CANDIDATES by it's type." |
+ |
712 |
(cond |
+ |
713 |
;; NOTE: Asynchronous |
+ |
714 |
((company-fuzzy--async-candidates-p candidates) |
+ |
715 |
(ignore-errors |
+ |
716 |
(funcall (cdr candidates) |
+ |
717 |
(lambda (async-candidates) |
+ |
718 |
(company-fuzzy--register-candidates backend async-candidates))))) |
+ |
719 |
;; NOTE: Synchronous |
+ |
720 |
;; |
+ |
721 |
;; This is the final ensure step before processing it to scoring phase. |
+ |
722 |
;; We confirm candidates by adding it to `company-fuzzy--candidates'. |
+ |
723 |
;; The function `company-fuzzy--valid-candidates-p' is use to ensure the |
+ |
724 |
;; candidates returns a list of strings, which this is the current only valid |
+ |
725 |
;; type to this package. |
+ |
726 |
((company-fuzzy--valid-candidates-p candidates) |
+ |
727 |
(company-fuzzy--register-candidates backend candidates)))) |
+ |
728 |
|
+ |
729 |
(defun company-fuzzy--get-prefix () |
+ |
730 |
"Set the prefix just right before completion." |
+ |
731 |
(setq company-fuzzy--is-trigger-prefix-p nil |
+ |
732 |
company-fuzzy--prefix (or (ignore-errors (company-fuzzy--furthest-prefix)) |
+ |
733 |
(ignore-errors (company-fuzzy--generic-prefix)) |
+ |
734 |
(ffap-guesser)) |
+ |
735 |
company-fuzzy--prefix-first (ignore-errors (substring company-fuzzy--prefix 0 1))) |
+ |
736 |
company-fuzzy--prefix) ; make sure return it |
+ |
737 |
|
+ |
738 |
(defun company-fuzzy-all-other-backends (command &optional arg &rest ignored) |
+ |
739 |
"Backend source for all other backend except this backend, COMMAND, ARG, IGNORED." |
+ |
740 |
(interactive (list 'interactive)) |
+ |
741 |
(cl-case command |
+ |
742 |
(`interactive (company-begin-backend 'company-fuzzy-all-other-backends)) |
+ |
743 |
(`prefix (company-fuzzy--get-prefix)) |
+ |
744 |
(`annotation (company-fuzzy--extract-annotation arg)) |
+ |
745 |
(`candidates (company-fuzzy-all-candidates)) |
+ |
746 |
(`pre-render (company-fuzzy--pre-render arg (nth 0 ignored))) |
+ |
747 |
(t (company-fuzzy--backend-command arg command)))) |
+ |
748 |
|
+ |
749 |
;; |
+ |
750 |
;; (@* "Users" ) |
+ |
751 |
;; |
+ |
752 |
|
+ |
753 |
(defun company-fuzzy--ensure-local () |
+ |
754 |
"Ensure modified variable effect locally." |
+ |
755 |
(make-local-variable 'company-fuzzy--backends) |
+ |
756 |
(make-local-variable 'company-fuzzy--recorded-backends) |
+ |
757 |
(make-local-variable 'company-backends)) |
+ |
758 |
|
+ |
759 |
(defun company-fuzzy--backend-organize () |
+ |
760 |
"Organize backend after modified the backend list." |
+ |
761 |
(if company-fuzzy-mode |
+ |
762 |
(setq company-fuzzy--backends (delete-dups company-fuzzy--backends) |
+ |
763 |
company-fuzzy--recorded-backends (delete-dups company-fuzzy--recorded-backends)) |
+ |
764 |
(setq company-backends (delete-dups company-backends)))) |
+ |
765 |
|
+ |
766 |
;;;###autoload |
+ |
767 |
(defun company-fuzzy-backend-add (backend) |
+ |
768 |
"Safe way to add BACKEND." |
+ |
769 |
(company-fuzzy--ensure-local) |
+ |
770 |
(if company-fuzzy-mode |
+ |
771 |
(progn |
+ |
772 |
(add-to-list 'company-fuzzy--backends backend t) |
+ |
773 |
(add-to-list 'company-fuzzy--recorded-backends backend t)) |
+ |
774 |
(add-to-list 'company-backends backend t)) |
+ |
775 |
(company-fuzzy--backend-organize)) |
+ |
776 |
|
+ |
777 |
;;;###autoload |
+ |
778 |
(defun company-fuzzy-backend-remove (backend) |
+ |
779 |
"Safe way to remove BACKEND." |
+ |
780 |
(company-fuzzy--ensure-local) |
+ |
781 |
(if company-fuzzy-mode |
+ |
782 |
(progn |
+ |
783 |
(setq company-fuzzy--backends (cl-remove backend company-fuzzy--backends) |
+ |
784 |
company-fuzzy--recorded-backends (cl-remove backend company-fuzzy--recorded-backends))) |
+ |
785 |
(setq company-backends (cl-remove backend company-backends))) |
+ |
786 |
(company-fuzzy--backend-organize)) |
+ |
787 |
|
+ |
788 |
(defun company-fuzzy--insert-to (list elm n) |
+ |
789 |
"Insert into list LIST an element ELM at index N. |
+ |
790 |
|
+ |
791 |
If N is 0, ELM is inserted before the first element. |
+ |
792 |
|
+ |
793 |
The resulting list is returned. As the list contents is mutated |
+ |
794 |
in-place, the old list reference does not remain valid." |
+ |
795 |
(let* ((padded-list (cons nil (copy-sequence list))) |
+ |
796 |
(c (nthcdr n padded-list))) |
+ |
797 |
(setcdr c (cons elm (cdr c))) |
+ |
798 |
(cdr padded-list))) |
+ |
799 |
|
+ |
800 |
(defun company-fuzzy--insert-before (list elm new-elm) |
+ |
801 |
"Add a NEW-ELM to the LIST before ELM." |
+ |
802 |
(let ((position (or (cl-position elm list :test 'equal) 0))) |
+ |
803 |
(company-fuzzy--insert-to list new-elm position))) |
+ |
804 |
|
+ |
805 |
(defun company-fuzzy--insert-after (list elm new-elm) |
+ |
806 |
"Add a NEW-ELM to the LIST after ELM." |
+ |
807 |
(let ((position (or (cl-position elm list :test 'equal) 0))) |
+ |
808 |
(company-fuzzy--insert-to list new-elm (1+ position)))) |
+ |
809 |
|
+ |
810 |
;;;###autoload |
+ |
811 |
(defun company-fuzzy-backend-add-before (backend target) |
+ |
812 |
"Add the BACKEND before the TARGET backend." |
+ |
813 |
(company-fuzzy--ensure-local) |
+ |
814 |
(if company-fuzzy-mode |
+ |
815 |
(setq company-fuzzy--backends |
+ |
816 |
(company-fuzzy--insert-before company-fuzzy--backends |
+ |
817 |
target backend) |
+ |
818 |
company-fuzzy--recorded-backends |
+ |
819 |
(company-fuzzy--insert-before company-fuzzy--recorded-backends |
+ |
820 |
target backend)) |
+ |
821 |
(setq company-backends |
+ |
822 |
(company-fuzzy--insert-before company-backends |
+ |
823 |
target backend))) |
+ |
824 |
(company-fuzzy--backend-organize)) |
+ |
825 |
|
+ |
826 |
;;;###autoload |
+ |
827 |
(defun company-fuzzy-backend-add-after (backend target) |
+ |
828 |
"Add the BACKEND after the TARGET backend." |
+ |
829 |
(company-fuzzy--ensure-local) |
+ |
830 |
(if company-fuzzy-mode |
+ |
831 |
(setq company-fuzzy--backends |
+ |
832 |
(company-fuzzy--insert-after company-fuzzy--backends |
+ |
833 |
target backend) |
+ |
834 |
company-fuzzy--recorded-backends |
+ |
835 |
(company-fuzzy--insert-after company-fuzzy--recorded-backends |
+ |
836 |
target backend)) |
+ |
837 |
(setq company-backends |
+ |
838 |
(company-fuzzy--insert-after company-backends |
+ |
839 |
target backend))) |
+ |
840 |
(company-fuzzy--backend-organize)) |
+ |
841 |
|
+ |
842 |
;; |
+ |
843 |
;; (@* "Plugins" ) |
+ |
844 |
;; |
+ |
845 |
|
+ |
846 |
(defun company-fuzzy--lsp-connected-p () |
+ |
847 |
"Return non-nil if lsp is connected." |
+ |
848 |
(or (bound-and-true-p lsp-managed-mode) |
+ |
849 |
(bound-and-true-p eglot--managed-mode))) |
+ |
850 |
|
+ |
851 |
(defun company-fuzzy--lsp-after-enabled (&rest _) |
+ |
852 |
"Hook run after LSP is enabled." |
+ |
853 |
(when (company-fuzzy--lsp-connected-p) |
+ |
854 |
;; No need to check for `company-fuzzy-mode' is on or not since this |
+ |
855 |
;; is hook only added when `company-fuzzy-mode' is on. |
+ |
856 |
(setq-local company-backends '(company-fuzzy-all-other-backends)))) |
+ |
857 |
|
+ |
858 |
(defun company-fuzzy--lsp-passthrough (backend) |
+ |
859 |
"Respect `capf' BACKEND when LSP is available." |
+ |
860 |
(when (memq backend '(company-capf)) |
+ |
861 |
(company-fuzzy--lsp-connected-p))) |
+ |
862 |
|
+ |
863 |
(defun company-fuzzy-yasnippet--completions-for-prefix (fnc &rest args) |
+ |
864 |
"Wrap around `company-yasnippet--completions-for-prefix' function in order to |
+ |
865 |
get all possible candidates. |
+ |
866 |
|
+ |
867 |
Arguments FNC and ARGS are used to apply original operations." |
+ |
868 |
(when company-fuzzy-mode |
+ |
869 |
;; `prefix' came from `company-fuzzy--backend-prefix-get', so we simply |
+ |
870 |
;; replace set `key-prefix' to `prefix'. |
+ |
871 |
(setf (nth 1 args) (nth 0 args))) |
+ |
872 |
(apply fnc args)) |
+ |
873 |
|
+ |
874 |
(provide 'company-fuzzy) |
+ |
875 |
;;; company-fuzzy.el ends here |
+ |
876 |
init.el ¶
12 additions and 39 deletions.
View changes Hide changes
1 |
1 |
;; Copyright © 2018-2022 Maarten Vangeneugden |
2 |
2 |
;; Author: Maarten Vangeneugden <contact_me@maartenv.be> |
3 |
3 |
;; URL: https://maartenv.be |
4 |
4 |
;; |
5 |
5 |
;; Welcome to Ghent Emacs. |
6 |
6 |
;; |
7 |
7 |
;; This is the configuration file for Ghent Emacs, a GNU Emacs derivative |
8 |
8 |
;; developed in the city of Ghent, Belgium, by a student of Engineering |
9 |
9 |
;; Informatics at Ghent University. |
10 |
10 |
;; |
11 |
11 |
;; License: GPLv3+ |
12 |
12 |
|
13 |
13 |
;; USAGE: |
14 |
14 |
;; This configuration file uses the use-package declaration, that means the |
15 |
15 |
;; settings are a bit different from what you'd normally do in a GNU Emacs |
16 |
16 |
;; init.el file. Consult https://github.com/jwiegley/use-package for info on how |
17 |
17 |
;; to correctly write package configuration. |
18 |
18 |
|
19 |
19 |
(eval-when-compile |
+ |
20 |
;; Do you get shit like "wrong number of arguments" that completely freezes up |
+ |
21 |
;; the autocompleter? Fix it by removing the company-fuzzy.elc file from the |
+ |
22 |
;; .emacs elpa layers directory, and replacing company-fuzzy.el with the |
+ |
23 |
;; company-fuzzy.el file in the rc repository. Just adding this fixes a bug that |
+ |
24 |
;; apparently nobody else on the internet has or has managed to figure out a fix for. |
+ |
25 |
|
+ |
26 |
|
+ |
27 |
(eval-when-compile |
20 |
28 |
(require 'use-package)) |
21 |
29 |
;(require 'diminish) ;; if you use :diminish |
22 |
30 |
(require 'bind-key) ;; if you use any :bind variant |
23 |
31 |
|
24 |
32 |
(custom-set-variables |
25 |
33 |
;; custom-set-variables was added by Custom. |
26 |
34 |
;; If you edit it by hand, you could mess it up, so be careful. |
27 |
35 |
;; Your init file should contain only one such instance. |
28 |
36 |
;; If there is more than one, they won't work right. |
29 |
37 |
'(custom-safe-themes |
30 |
38 |
'("763bf89898a06b03f7b65fbc29857a1c292e4350246093702fdbd6c4e46e2cf0" "78e6be576f4a526d212d5f9a8798e5706990216e9be10174e3f3b015b8662e27" "d9646b131c4aa37f01f909fbdd5a9099389518eb68f25277ed19ba99adeb7279" "8b58ef2d23b6d164988a607ee153fd2fa35ee33efc394281b1028c2797ddeebb" "f9aede508e587fe21bcfc0a85e1ec7d27312d9587e686a6f5afdbb0d220eab50" "83ae405e25a0a81f2840bfe5daf481f74df0ddb687f317b5e005aa61261126e9" "c433c87bd4b64b8ba9890e8ed64597ea0f8eb0396f4c9a9e01bd20a04d15d358" "a24c5b3c12d147da6cef80938dca1223b7c7f70f2f382b26308eba014dc4833a" "732b807b0543855541743429c9979ebfb363e27ec91e82f463c91e68c772f6e3" "a2cde79e4cc8dc9a03e7d9a42fabf8928720d420034b66aecc5b665bbf05d4e9" "8aebf25556399b58091e533e455dd50a6a9cba958cc4ebb0aab175863c25b9a4" "bd7b7c5df1174796deefce5debc2d976b264585d51852c962362be83932873d9" default)) |
31 |
39 |
'(inhibit-startup-screen t) |
32 |
40 |
'(org-agenda-files nil nil nil "Customized with use-package org") |
33 |
- | '(package-selected-packages |
34 |
41 |
'(company-fuzzy web-mode use-package srefactor spacemacs-theme spaceline solarized-theme rainbow-delimiters pretty-mode page-break-lines monokai-theme helm general evil dashboard dante company-ycmd company-flx company-anaconda clang-format auto-package-update auctex a)) |
35 |
- | '(spaceline-inflation 1 t nil "Customized with use-package spaceline") |
+ |
42 |
'(spaceline-inflation 1 t nil "Customized with use-package spaceline") |
36 |
43 |
'(spaceline-toggle-buffer-size-off nil t nil "Customized with use-package spaceline") |
37 |
44 |
'(warning-suppress-types '((comp)))) |
38 |
45 |
;(custom-set-faces |
39 |
46 |
;; custom-set-faces was added by Custom. |
40 |
47 |
;; If you edit it by hand, you could mess it up, so be careful. |
41 |
48 |
;; Your init file should contain only one such instance. |
42 |
49 |
;; If there is more than one, they won't work right. |
43 |
50 |
;'(default ((((class color) (min-colors 89)) (:foreground "#ffffff" :background "#263238"))))) |
44 |
51 |
|
45 |
52 |
|
46 |
53 |
(add-to-list 'default-frame-alist |
47 |
54 |
'(font . "Hack-11")) |
48 |
55 |
|
49 |
56 |
;; To get rid of those FUCKING ANNOYING BACKUP FILES FUCKING HELL DUDE |
50 |
57 |
(setq backup-directory-alist '(("." . "~/.emacs.d/backup")) |
51 |
58 |
backup-by-copying t ; Don't delink hardlinks |
52 |
59 |
version-control t ; Use version numbers on backups |
53 |
60 |
delete-old-versions t ; Automatically delete excess backups |
54 |
61 |
kept-new-versions 20 ; how many of the newest versions to keep |
55 |
62 |
kept-old-versions 5 ; and how many of the old |
56 |
63 |
) |
57 |
64 |
;; And yes I copied it from SO, suck it: https://stackoverflow.com/questions/2680389/how-to-remove-all-files-ending-with-made-by-emacs |
58 |
65 |
|
59 |
66 |
;; Disables the use of tabs, replaces them with spaces |
60 |
67 |
(setq-default indent-tabs-mode nil) |
61 |
68 |
|
62 |
69 |
;; Activate UTF-8 throughout Ghent Emacs |
63 |
70 |
(prefer-coding-system 'utf-8) |
64 |
71 |
(set-default-coding-systems 'utf-8) |
65 |
72 |
(set-terminal-coding-system 'utf-8) |
66 |
73 |
(set-keyboard-coding-system 'utf-8) |
67 |
74 |
(setq x-select-request-type '(UTF8_STRING COMPOUND_TEXT TEXT STRING)) |
68 |
75 |
|
69 |
76 |
;; Line numbering config |
70 |
77 |
(global-display-line-numbers-mode) |
71 |
78 |
(setq display-line-numbers-mode t) |
72 |
79 |
(setq display-line-numbers-widen t) |
73 |
80 |
(setq display-line-numbers-type 'relative) |
74 |
81 |
(setq display-line-numbers-current-absolute t) |
75 |
82 |
|
76 |
83 |
(setq mouse-wheel-scroll-amount '(1 ((shift) . 1))) |
77 |
84 |
(setq scroll-step 1) |
78 |
85 |
(setq scroll-margin 10) ;; Keeps 10 lines above and down always visible if still left |
79 |
86 |
|
80 |
87 |
;; Enable line breaks in all modes at column 80 |
81 |
88 |
(setq-default auto-fill-function 'do-auto-fill) |
82 |
89 |
(setq-default fill-column 80) |
83 |
90 |
|
84 |
91 |
(setq ring-bell-function 'ignore) ;; Disables the FUCKING ANNOYING BEEPS HOLY SHIT |
85 |
92 |
|
86 |
93 |
;; Setup packages |
87 |
94 |
;(package-initialize) |
88 |
95 |
(require 'package) |
89 |
96 |
(setq package-enable-at-startup nil) |
90 |
97 |
(add-to-list 'package-archives '("org" . "https://orgmode.org/elpa/")) |
91 |
98 |
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/")) |
92 |
99 |
(unless (package-installed-p 'use-package) |
93 |
100 |
(package-refresh-contents) |
94 |
101 |
(package-install 'use-package)) |
95 |
102 |
|
96 |
103 |
|
97 |
104 |
|
98 |
105 |
|
99 |
106 |
;; Next two lines allow foregoing :ensure t on all packages |
100 |
107 |
;; :ensure t simply makes sure that, if a package isn't installed on this |
101 |
108 |
;; machine, it's automatically fetched and installed. |
102 |
109 |
;; This doesn't keep packages up-to-date, cfr. auto-package-update for that |
103 |
110 |
(require 'use-package-ensure) |
104 |
111 |
(setq use-package-always-ensure t) |
105 |
112 |
|
106 |
113 |
;; Package for automatic updating of all the other packages |
107 |
114 |
(use-package auto-package-update |
108 |
115 |
:config |
109 |
116 |
(setq auto-package-update-delete-old-versions t) |
110 |
117 |
(setq auto-package-update-hide-results t) |
111 |
118 |
(auto-package-update-maybe)) |
112 |
119 |
|
113 |
120 |
;; Easier keybindings so we can do more lazy loading |
114 |
121 |
(use-package general |
115 |
122 |
:config |
116 |
123 |
(general-create-definer my-leader-def |
117 |
124 |
;; :prefix my-leader |
118 |
125 |
:prefix "SPC") |
119 |
126 |
(general-create-definer local-leader-def |
120 |
127 |
;; :prefix local-leader |
121 |
128 |
:prefix ",")) |
122 |
129 |
|
123 |
130 |
(use-package dashboard |
124 |
131 |
:init |
125 |
132 |
(setq dashboard-banner-logo-title "") ; It's nicer to just not have a title text. |
126 |
133 |
(setq dashboard-startup-banner "~/ghent-emacs.png") |
127 |
134 |
:config |
128 |
135 |
(dashboard-setup-startup-hook)) |
129 |
136 |
|
130 |
137 |
;; AUCTeX configuration |
131 |
138 |
;; Partly inspired by https://piotr.is/2010/emacs-as-the-ultimate-latex-editor/ |
132 |
139 |
;;;;(use-package auctex |
133 |
140 |
;;:init |
134 |
141 |
;;(setq TeX-auto-save t) |
135 |
142 |
;;(setq TeX-parse-self t) |
136 |
143 |
;;(setq Tex-save-query nil) |
137 |
144 |
;;) |
138 |
145 |
|
139 |
146 |
;; Updates all packages automatically |
140 |
147 |
(use-package auto-package-update |
141 |
148 |
:config |
142 |
149 |
(setq auto-package-update-delete-old-versions t) |
143 |
150 |
(setq auto-package-update-hide-results t) |
144 |
151 |
(auto-package-update-maybe)) |
145 |
152 |
|
146 |
153 |
;; UI settings |
147 |
154 |
(tool-bar-mode -1) |
148 |
155 |
(menu-bar-mode -1) |
149 |
156 |
(toggle-scroll-bar -1) |
150 |
157 |
|
151 |
158 |
;; Tabs and width |
152 |
159 |
(setq-default tab-width 4) |
153 |
160 |
(setq-default c-basic-offset 4) |
154 |
161 |
|
155 |
162 |
(use-package spaceline |
156 |
163 |
:init |
157 |
164 |
(setq frame-char-height 35) |
158 |
165 |
(setq powerline-height 35) |
159 |
166 |
:custom |
160 |
167 |
(spaceline-toggle-buffer-size-off) |
161 |
168 |
;(setq powerline-height 21) |
162 |
169 |
(spaceline-inflation 1) |
163 |
170 |
(powerline-default-separator 'slant) |
164 |
171 |
:config |
165 |
172 |
(spaceline-spacemacs-theme) |
166 |
173 |
(setq spaceline-highlight-face-func 'spaceline-highlight-face-evil-state)) |
167 |
174 |
|
168 |
175 |
|
169 |
176 |
(use-package monokai-theme |
170 |
177 |
:config |
171 |
178 |
(load-theme 'monokai t) |
172 |
179 |
(setq monokai-variable-pitch-mode t)) |
173 |
180 |
;; When using solarized as theme, put in :config |
174 |
181 |
;; (setq x-underline-at-descent-line t) |
175 |
182 |
;; Which will block an ugly line being drawn trhough the modeline. |
176 |
183 |
|
177 |
184 |
;(add-hook 'org-mode-hook '(lambda () (setq fill-column 80))) |
178 |
185 |
;(add-hook 'org-mode-hook 'auto-fill-mode) |
179 |
186 |
;; (Programming) languages |
180 |
187 |
|
181 |
188 |
|
182 |
189 |
|
183 |
190 |
(use-package dante |
184 |
191 |
:after haskell-mode |
185 |
192 |
:commands 'dante-mode |
186 |
193 |
:init |
187 |
194 |
(add-hook 'haskell-mode-hook 'dante-mode) |
188 |
195 |
(add-hook 'haskell-mode-hook 'flycheck-mode) |
189 |
196 |
(add-hook 'haskell-mode-hook ' |
190 |
197 |
(lambda () (modify-syntax-entry ?_ "w"))) |
191 |
198 |
) |
192 |
199 |
|
193 |
200 |
|
194 |
201 |
;; HTML/CSS/Django |
195 |
202 |
(use-package web-mode |
196 |
203 |
:mode "\\.html?\\.djhtml\\'" |
197 |
204 |
:init |
198 |
205 |
(add-to-list 'auto-mode-alist '("\\.djhtml\\'" . web-mode)) |
199 |
206 |
(setq web-mode-markup-indent-offset 4) |
200 |
207 |
(setq web-mode-css-indent-offset 4) |
201 |
208 |
(setq web-mode-code-indent-offset 4) |
202 |
209 |
;(setq web-mode-engines-alist |
203 |
210 |
; '(("django" . "\\.html\\"))) ;; FIXME this doesn't work yet. IDK why. |
204 |
211 |
:custom ;; Next lines disable all the automatic completion stuff that I didn't explicitely ask for |
205 |
212 |
(web-mode-enable-auto-pairing nil) |
206 |
213 |
(web-mode-enable-auto-closing nil) |
207 |
214 |
(web-mode-enable-auto-expanding nil) |
208 |
215 |
(web-mode-enable-auto-opening nil) |
209 |
216 |
(web-mode-enable-auto-quoting nil)) |
210 |
217 |
|
211 |
218 |
|
212 |
219 |
;;(use-package ycmd-mode |
213 |
- | ;;:ensure ycmd |
214 |
- | ;;;:hook (after-init . global-ycmd-mode) |
215 |
- | ;;:hook (haskell-mode elisp-mode python-mode c-mode c++-mode) ; Add the modes of the languages where YCM |
216 |
- | ;;; needs to kick in |
217 |
- | ;;:init |
218 |
- | ;;; Old paths |
219 |
- | ;;;(set-variable 'ycmd-server-command `("/usr/bin/python" ,(file-truename "/usr/share/vim/vimfiles/third_party/ycmd/ycmd/"))) |
220 |
- | ;;;(set-variable 'ycmd-global-config "/home/simba/.emacs.d/lang/ycm_conf.py") |
221 |
- | ;;(set-variable 'ycmd-server-command `("python" ,(file-truename "~/ycmd/ycmd"))) |
222 |
- | ;;(set-variable 'ycmd-global-config (file-truename "~/Repositories/rc/.ycm_extra_conf.py")) |
223 |
- | ;;(set-variable 'ycmd-global-modes 'all) ; Activates YCMD in 'all' major modes, |
224 |
- | ;;; not only those in ycmd-file-type-map |
225 |
- | ;;;(set-variable 'ycmd-extra-conf-whitelist '("/home/jorrit/Dev/*")) |
226 |
- | ;;:config |
227 |
- | ;;(setq url-show-status nil) ; Makes those FUCKING annoying messages SHUT THE HELL UP |
228 |
- | ;;(setq request-message-level -1) |
229 |
- | |
230 |
- | ;;(use-package flycheck-ycmd |
231 |
- | ;;:ensure t |
232 |
- | ;;:commands (flycheck-ycmd-setup) |
233 |
- | ;;:hook (ycmd-mode . flycheck-ycmd-setup) |
234 |
- | ;;:init |
235 |
- | ;;(setq flycheck-clang-language-standard "c++11") |
236 |
- | ;;(when (not (display-graphic-p)) |
237 |
- | ;;(setq flycheck-indication-mode nil)))) |
238 |
- | |
239 |
- | (use-package company |
240 |
220 |
:hook (after-init . global-company-mode) |
241 |
221 |
:init |
242 |
222 |
(company-tng-configure-default) ; Use <TAB> to scroll in completion options |
243 |
223 |
(setq company-minimum-prefix-length 2) |
244 |
224 |
(setq company-idle-delay 0.0)) |
245 |
225 |
;:config |
246 |
- | ;;(use-package company-ycmd-mode |
247 |
- | ;;:ensure company-ycmd |
248 |
- | ;;:commands (company-ycmd-setup) |
249 |
- | ;;:hook (ycmd-mode . company-ycmd-setup)) |
250 |
- | ;;(use-package company-flx |
251 |
- | ;;:ensure t |
252 |
- | ;;:config |
253 |
- | ;;(company-flx-mode +1))) |
254 |
- | ;; |
255 |
- | (use-package company-fuzzy |
+ |
226 |
|
+ |
227 |
(use-package company-fuzzy |
256 |
228 |
:hook (company-mode . company-fuzzy-mode) |
257 |
229 |
:init |
258 |
230 |
(setq company-fuzzy-sorting-backend 'flx |
259 |
231 |
company-fuzzy-prefix-on-top nil |
+ |
232 |
company-fuzzy-prefix-on-top nil |
260 |
233 |
company-fuzzy-history-backends '(company-yasnippet) |
261 |
234 |
company-fuzzy-trigger-symbols '("." "->" "<" "\"" "'" "@"))) |
262 |
235 |
|
263 |
236 |
(global-company-fuzzy-mode 1) |
264 |
237 |
|
265 |
238 |
(use-package clang-format |
266 |
239 |
:general |
267 |
240 |
(local-leader-def |
268 |
241 |
:states 'normal |
269 |
242 |
:modes '(c-mode-map c++-mode-map) |
270 |
243 |
"b" '(:ignore t :which-key "clang") |
271 |
244 |
"bf" 'clang-format-buffer) |
272 |
245 |
:init |
273 |
246 |
(setq-default clang-format-style "{BasedOnStyle: llvm, IndentWidth: 4}")) |
274 |
247 |
|
275 |
248 |
;; eViL-mode |
276 |
249 |
(use-package evil |
277 |
250 |
:hook (after-init . evil-mode) |
278 |
251 |
:bind (:map evil-normal-state-map ;; Scrolls over lines correctly |
279 |
252 |
("j" . evil-next-visual-line) |
280 |
253 |
("k" . evil-previous-visual-line)) |
281 |
254 |
:general |
282 |
255 |
(my-leader-def |
283 |
256 |
:states 'normal |
284 |
257 |
"b" '(:ignore t :which-key "buffer") |
285 |
258 |
"g" '(:ignore t :which-key "magit") |
286 |
259 |
"f" '(:ignore t :which-key "files") |
287 |
260 |
"bk" 'kill-this-buffer |
288 |
261 |
"bd" 'kill-other-buffers |
289 |
262 |
"bh" 'switch-to-home-buffer |
290 |
263 |
"br" 'revert-buffer |
291 |
264 |
"h" 'split-window-vertically |
292 |
265 |
"v" 'split-window-horizontally) |
293 |
266 |
(local-leader-def |
294 |
267 |
:states 'normal |
295 |
268 |
;; General lang options |
296 |
269 |
"c" 'compile) |
297 |
270 |
:init |
298 |
271 |
(setq evil-find-skip-newlines t) ;; Allows f/F/t/T to search beyond CR/LF |
299 |
272 |
(setq evil-undo-system 'undo-redo) ;; Just uses standard undo-redo behaviour |
300 |
273 |
;; a normal human expects |
301 |
274 |
(setq evil-want-C-u-scroll t)) ;; Activates c-u scroll to above. |
302 |
275 |
|
303 |
276 |
;; About smooth-scrolling: I'd normally just use some variables for scrolling |
304 |
277 |
;; but they all fail with org-mode. This package fixes everything that's wrong for me. |
305 |
278 |
;(use-package smooth-scrolling |
306 |
279 |
;:config |
307 |
280 |
;(smooth-scrolling-mode 1)) |
308 |
281 |
|
309 |
282 |
(use-package org |
310 |
283 |
:pin "org" |
311 |
284 |
; FIXME This causes some errors with bind-keys or what have you. Commented |
312 |
285 |
; until it is fixed. |
313 |
286 |
;:bind (:bind-keymap |
314 |
287 |
; ("C-c x" . org-todo-state-map) |
315 |
288 |
; :map org-todo-state-map |
316 |
289 |
; ("x" . #'(lambda nil (interactive) (org-todo "CANCELLED"))) |
317 |
290 |
; ("d" . #'(lambda nil (interactive) (org-todo "DONE"))) |
318 |
291 |
; ("f" . #'(lambda nil (interactive) (org-todo "DEFERRED"))) |
319 |
292 |
; ("l" . #'(lambda nil (interactive) (org-todo "DELEGATED"))) |
320 |
293 |
; ("s" . #'(lambda nil (interactive) (org-todo "STARTED"))) |
321 |
294 |
; ("w" . #'(lambda nil (interactive) (org-todo "WAITING")))) |
322 |
295 |
; :map org-mode-map |
323 |
296 |
; ("C-c x" . org-todo-state-map)) |
324 |
297 |
:init |
325 |
298 |
(define-key mode-specific-map [?a] 'org-agenda) |
326 |
299 |
:custom |
327 |
300 |
;; Because I use XeLaTeX (it's objectively better), some variables need to be |
328 |
301 |
;; set so org-mode knows what to call. |
329 |
302 |
|
330 |
303 |
;; Okay, so you cán export asynchronous so compiling your PDF doesn't lock up |
331 |
304 |
;; the editor completely, but for one reason or another, you MUST set the |
332 |
305 |
;; async-debug to nil. Otherwise it will constantly "exit abnormally" without |
333 |
306 |
;; reason. This fixes it, who knows why. |
334 |
307 |
(org-export-async-debug nil) |
335 |
308 |
|
336 |
309 |
(org-latex-compiler 'xelatex) ; Makes sure the XeLaTeX compiler is used |
337 |
310 |
|
338 |
311 |
; Tells Org to use dvisvgm because dvipng does not support XeLaTeX's output format |
339 |
312 |
(org-preview-latex-default-process 'dvisvgm) |
340 |
313 |
|
341 |
314 |
; This edits the preview process so it works correctly with XeLaTeX. |
342 |
315 |
; Changes: |
343 |
316 |
; - "latex" to "xelatex" |
344 |
317 |
; - Added the "-no-pdf" flag so it prints an XDV file instead of PDF. |
345 |
318 |
; - change input type from dvi to xdv |
346 |
319 |
; - Only leave the dvisvgm option because I don't need the others |
347 |
320 |
(org-preview-latex-process-alist |
348 |
321 |
(quote |
349 |
322 |
((dvisvgm :programs |
350 |
323 |
("xelatex" "dvisvgm") |
351 |
324 |
:description "dvi > svg" :message "you need to install the programs: xelatex and dvisvgm." :use-xcolor t :image-input-type "xdv" :image-output-type "svg" :image-size-adjust |
352 |
325 |
(1.7 . 1.5) |
353 |
326 |
:latex-compiler |
354 |
327 |
("xelatex -interaction nonstopmode -no-pdf -output-directory %o %f") |
355 |
328 |
:image-converter |
356 |
329 |
("dvisvgm %f -n -b min -c %S -o %O"))))) |
357 |
330 |
|
358 |
331 |
;; Sets the formatting options. I only changed :scale to 1.6, but I don't know |
359 |
332 |
;; how to change only thát, so for now I'm configuring the entire variable |
360 |
333 |
(org-format-latex-options (quote |
361 |
334 |
(:foreground default :background default :scale 1.6 :html-foreground "Black" :html-background "Transparent" :html-scale 1.0 :matchers |
362 |
335 |
("begin" "$1" "$" "$$" "\\(" "\\[")))) |
363 |
336 |
|
364 |
337 |
;; Sets the directory in which the preview fragments are stored to the /tmp |
365 |
338 |
;; folder. Otherwise it clutters up the folder in which the source resides |
366 |
339 |
;; with what are essentially cache files. |
367 |
340 |
(org-preview-latex-image-directory "/tmp/ltximg/") |
368 |
341 |
|
369 |
342 |
;; Following customizations are in regard to org-agenda configuration. |
370 |
343 |
(org-agenda-files (quote ("~/shared/planning/planning.org"))) |
371 |
344 |
(org-default-notes-file "~/shared/planning/notes.org") |
372 |
345 |
(org-agenda-span 62) |
373 |
346 |
(org-deadline-warning-days 14) |
374 |
347 |
(org-agenda-show-all-dates t) |
375 |
348 |
(org-agenda-skip-deadline-if-done t) |
376 |
349 |
(org-agenda-skip-scheduled-if-done t) |
377 |
350 |
(org-agenda-start-on-weekday nil) |
378 |
351 |
(org-reverse-note-order t) |
379 |
352 |
(org-fast-tag-selection-single-key (quote expert)) |
380 |
353 |
(org-agenda-custom-commands |
381 |
354 |
(quote (("d" todo "DELEGATED" nil) |
382 |
355 |
("c" todo "DONE|DEFERRED|CANCELED" nil) |
383 |
356 |
("w" todo "WAITING" nil) |
384 |
357 |
("W" agenda "" ((org-agenda-ndays 21))) |
385 |
358 |
("A" agenda "" |
386 |
359 |
((org-agenda-skip-function |
387 |
360 |
(lambda nil |
388 |
361 |
(org-agenda-skip-entry-if (quote notregexp) "\\=.*\\[#A\\]"))) |
389 |
362 |
(org-agenda-ndays 1) |
390 |
363 |
(org-agenda-overriding-header "Today's Priority #A tasks: "))) |
391 |
364 |
("u" alltodo "" |
392 |
365 |
((org-agenda-skip-function |
393 |
366 |
(lambda nil |
394 |
367 |
(org-agenda-skip-entry-if (quote scheduled) (quote deadline) |
395 |
368 |
(quote regexp) "\n]+>"))) |
396 |
369 |
(org-agenda-overriding-header "Unscheduled TODO entries: ")))))) |
397 |
370 |
(org-capture-store-without-prompt t) |
398 |
371 |
(org-capture-templates |
399 |
372 |
(quote ((116 "* TODO %?\n %u" "~/Repositories/private/org/planning.org" "Tasks") |
400 |
373 |
(110 "* %u %?" "~/Repositories/private/org/notes.org" "Notes")))) |
401 |
374 |
(capture-annotation-functions (quote (org-capture-annotation))) |
402 |
375 |
(capture-handler-functions (quote (org-capture-handler)))) |
403 |
376 |
|
404 |
377 |
;:general |
405 |
378 |
;(local-leader-def |
406 |
379 |
; :states 'normal |
407 |
380 |
; :keymaps 'org-mode-map |
408 |
381 |
; "e" 'org-export-dispatch |
409 |
382 |
; "x" 'org-table-export |
410 |
383 |
; "." 'org-time-stamp |
411 |
384 |
; "t" 'org-twbs-export-to-html |
412 |
385 |
; "s" 'org-schedule |
413 |
386 |
; "d" 'org-deadline |
414 |
387 |
; "'" 'org-edit-special) |
415 |
388 |
; :config |
416 |
389 |
; ;; log todo items with timestamp |
417 |
390 |
; (setq org-log-done 'time)) |
418 |
391 |
|
419 |
392 |
(use-package helm |
420 |
393 |
:hook (after-init . helm-mode) |
421 |
394 |
:commands (helm-autoresize-mode) |
422 |
395 |
:init |
423 |
396 |
;; (defvar helm-google-suggest-use-curl-p) |
424 |
397 |
(defvar helm-ff-search-library-in-sexp) |
425 |
398 |
(defvar helm-echo-input-in-header-line) |
426 |
399 |
(defvar helm-ff-file-name-history-use-recentf) |
427 |
400 |
:general |
428 |
401 |
(general-define-key |
429 |
402 |
"M-x" 'helm-M-x |
430 |
403 |
"M-:" 'helm-eval-expression |
431 |
404 |
"C-c h" 'helm-command-prefix) |
432 |
405 |
(general-define-key |
433 |
406 |
:keymaps 'helm-map |
434 |
407 |
"<tab>" 'helm-execute-persistent-action |
435 |
408 |
"C-i" 'helm-execute-persistent-action |
436 |
409 |
"C-z" 'helm-select-action) |
437 |
410 |
(my-leader-def |
438 |
411 |
:states 'normal |
439 |
412 |
"bb" 'helm-buffers-list |
440 |
413 |
"ff" 'helm-find-files |
441 |
414 |
"p" 'helm-show-kill-ring) |
442 |
415 |
:config |
443 |
416 |
(setq helm-split-window-inside-p t ; open helm buffer inside current window, not occupy whole other window |
444 |
417 |
helm-move-to-line-cycle-in-source t ; move to end or beginning of source when reaching top or bottom of source. |
445 |
418 |
helm-ff-search-library-in-sexp t ; search for library in `require' and `declare-function' sexp. |
446 |
419 |
helm-scroll-amount 8 ; scroll 8 lines other window using m-<next>/m-<prior> |
447 |
420 |
helm-ff-file-name-history-use-recentf t |
448 |
421 |
helm-echo-input-in-header-line t) |
449 |
422 |
|
450 |
423 |
;; hide some autogenerated files from helm |
451 |
424 |
(setq helm-ff-skip-boring-files t) |
452 |
425 |
;; (add-to-list 'helm-boring-file-regexp-list "\\~$") |
453 |
426 |
|
454 |
427 |
(setq helm-autoresize-max-height 0) |
455 |
428 |
(setq helm-autoresize-min-height 20) |
456 |
429 |
(helm-autoresize-mode 1)) |
457 |
430 |
|
458 |
431 |
|
459 |
432 |
(use-package rainbow-delimiters |
460 |
433 |
:hook (prog-mode . rainbow-delimiters-mode)) |
461 |
434 |
|
462 |
435 |
;; Settings for having an LaTeX beamer class export tool |
463 |
436 |
(unless (boundp 'org-export-latex-classes) |
464 |
437 |
(setq org-export-latex-classes nil)) |
465 |
438 |
(add-to-list 'org-export-latex-classes |
466 |
439 |
;; beamer class, for presentations |
467 |
440 |
'("beamer" |
468 |
441 |
"\\documentclass[11pt]{beamer}\n |
469 |
442 |
\\mode<{{{beamermode}}}>\n |
470 |
443 |
\\usetheme{{{{beamertheme}}}}\n |
471 |
444 |
\\usecolortheme{{{{beamercolortheme}}}}\n |
472 |
445 |
\\beamertemplateballitem\n |
473 |
446 |
\\setbeameroption{show notes} |
474 |
447 |
\\usepackage[utf8]{inputenc}\n |
475 |
448 |
\\usepackage[T1]{fontenc}\n |
476 |
449 |
\\usepackage{hyperref}\n |
477 |
450 |
\\usepackage{color} |
478 |
451 |
\\usepackage{listings} |
479 |
452 |
\\lstset{numbers=none,language=[ISO]C++,tabsize=4, |
480 |
453 |
frame=single, |
481 |
454 |
basicstyle=\\small, |
482 |
455 |
showspaces=false,showstringspaces=false, |
483 |
456 |
showtabs=false, |
484 |
457 |
keywordstyle=\\color{blue}\\bfseries, |
485 |
458 |
commentstyle=\\color{red}, |
486 |
459 |
}\n |
487 |
460 |
\\usepackage{verbatim}\n |
488 |
461 |
\\institute{{{{beamerinstitute}}}}\n |
489 |
462 |
\\subject{{{{beamersubject}}}}\n" |
490 |
463 |
|
491 |
464 |
("\\section{%s}" . "\\section*{%s}") |
492 |
465 |
|
493 |
466 |
("\\begin{frame}[fragile]\\frametitle{%s}" |
494 |
467 |
"\\end{frame}" |
495 |
468 |
"\\begin{frame}[fragile]\\frametitle{%s}" |
496 |
469 |
"\\end{frame}"))) |
497 |
470 |
|
498 |
471 |
;; Adds a letter class, for formal letters |
499 |
472 |
|
500 |
473 |
(add-to-list 'org-export-latex-classes |
501 |
474 |
|
502 |
475 |
'("letter" |
503 |
476 |
"\\documentclass[11pt]{letter}\n |
504 |
477 |
\\usepackage[utf8]{inputenc}\n |
505 |
478 |
\\usepackage[T1]{fontenc}\n |
506 |
479 |
\\usepackage{color}" |
507 |
480 |
|
508 |
481 |
("\\section{%s}" . "\\section*{%s}") |
509 |
482 |
("\\subsection{%s}" . "\\subsection*{%s}") |
510 |
483 |
("\\subsubsection{%s}" . "\\subsubsection*{%s}") |
511 |
484 |
("\\paragraph{%s}" . "\\paragraph*{%s}") |
512 |
485 |
("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) |
513 |
486 |
|
514 |
487 |
|
515 |
488 |
(custom-set-faces |
516 |
489 |
;; custom-set-faces was added by Custom. |
517 |
490 |
;; If you edit it by hand, you could mess it up, so be careful. |
518 |
491 |
;; Your init file should contain only one such instance. |
519 |
492 |
;; If there is more than one, they won't work right. |
520 |
493 |
'(default ((t (:background nil))))) |
521 |
494 |
|
522 |
495 |
|
523 |
496 |
;; This is to fix the retarded scrolling behaviour in Emacs as much as possible: |
524 |
497 |
(setq redisplay-dont-pause t |
525 |
498 |
scroll-margin 1 |
526 |
499 |
scroll-step 1 |
527 |
500 |
scroll-conservatively 10000 |
528 |
501 |
scroll-preserve-screen-position 1) |
529 |
502 |
;; Stops Emacs from accelerating my scroll: |
530 |
503 |
(setq mouse-wheel-progressive-speed nil) |
531 |
504 |
;; Makes scrolling do 5 lines at a time, otherwise it's pretty slow |
532 |
505 |
(setq mouse-wheel-scroll-amount '(2)) |
533 |
506 |