]> Git — Sourcephile - julm/julm-nix.git/blob - homes/programs/emacs/config.el
julm: stub mate-terminal to open in terminal in caja
[julm/julm-nix.git] / homes / programs / emacs / config.el
1 ;;; config.el -*- lexical-binding: t; -*-
2
3 ;; DOC: https://git.v0.io/hlissner/doom-emacs/src/commit/a680a4c96d2b57fcb75635bd1a918e1235e72890/docs/api.org
4 ;; DOC: https://github.com/daviwil/emacs-from-scratch
5
6 (setq user-full-name "Julien Moutinho"
7 user-mail-address "julm@sourcephile.fr"
8 )
9
10 ;; Line numbers are pretty slow all around. The performance boost of
11 ;; disabling them outweighs the utility of always keeping them on.
12 (setq display-line-numbers-type nil)
13
14 ;; Focus new window after splitting
15 (setq evil-split-window-below t
16 evil-vsplit-window-right t
17 )
18
19 ;; Undo
20 (setq undo-tree-auto-save-history t
21 undo-tree-history-directory-alist '(("." . "~/.cache/emacs/undo"))
22 )
23
24 ;; Fonts
25 (setq doom-font-increment 1
26 doom-font-size 9
27 ;doom-font-name "DejaVu Sans Mono"
28 doom-font-name "Hack"
29 ;doom-font-name "Unifont"
30 doom-font (font-spec :family doom-font-name :size doom-font-size :antialias t)
31 doom-unicode-font (font-spec :family "Symbola" :antialias t)
32 doom-variable-pitch-font (font-spec :family doom-font-name :antialias t)
33 ivy-posframe-font (font-spec :family doom-font-name :antialias t)
34 )
35 (setq x-underline-at-descent-line t)
36
37 ;; Dashboard
38 ;;(setq +doom-dashboard-banner-file (expand-file-name "banner.png" doom-private-dir))
39 (defun bury-messages-and-scratch ()
40 (mapcar #'bury-buffer '("*Messages*" "*scratch*")))
41 (add-hook 'emacs-startup-hook #'bury-messages-and-scratch)
42
43 ;; Formatting
44 (setq haskell-stylish-on-save nil)
45 (setq lsp-haskell-formatting-provider "fourmolu")
46 (setq +format-on-save-enabled-modes
47 '(not emacs-lisp-mode ; works well enough without it
48 sql-mode ; sqlformat is broken
49 tex-mode ; latexindent is broken
50 latex-mode ; latexindent is broken
51 bibtex-mode ; is broken
52 ess-r-mode ; styler takes forever
53 )
54 )
55
56 ;; Theming
57 (setq doom-theme 'doom-vibrant)
58 (custom-theme-set-faces! '(doom-vibrant)
59 '(default :background "black" :foreground "white")
60 '(hl-line :background "black")
61 '(cursor :background "DarkOrange" :foreground "black")
62 ;; Haskell colors
63 '(font-lock-string-face :foreground "magenta")
64 '(highlight-numbers-number :foreground "DeepSkyBlue" :bold t)
65 '(font-lock-comment-face :foreground "cyan3")
66 '(font-lock-doc-face :foreground "cyan1")
67 ;'(haskell-constructor-face :foreground "#c4451d")
68 ;'(haskell-keyword-face :foreground "#af005f")
69 ;'(haskell-keyword-face :foreground "RoyalBlue")
70 ;'(haskell-keyword-face :foreground "#44385f")
71 ;'(haskell-keyword-face :foreground "#906238" :bold t)
72 ;'(haskell-keyword-face :foreground "green4" :bold t)
73 '(haskell-keyword-face :foreground "LightGreen" :bold nil)
74 ;'(haskell-pragma-face :foreground "#2aa198")
75 '(haskell-pragma-face :foreground "#8f4e8b")
76 ;'(haskell-type-face :foreground "#9e358f")
77 '(haskell-operator-face :foreground "yellow" :bold nil)
78 ;'(haskell-type-face :foreground "SaddleBrown")
79 ;'(haskell-constructor-face :foreground "darkgoldenrod4")
80 '(haskell-definition-face :foreground "white" :bold nil)
81 '(swiper-line-face :background "grey15")
82 '(swiper-match-face-1 :foreground "grey50" :background "black") ; what is between matches
83 '(swiper-match-face-2 :foreground "black" :background "yellow2")
84 '(swiper-match-face-3 :foreground "black" :background "yellow3")
85 '(swiper-match-face-4 :foreground "black" :background "yellow4")
86 '(swiper-background-match-face-2 :foreground "black" :background "yellow2")
87 '(swiper-background-match-face-3 :foreground "black" :background "yellow3")
88 '(swiper-background-match-face-4 :foreground "black" :background "yellow4")
89 '(evil-ex-lazy-highlight :foreground "black" :background "yellow2")
90 '(region :foreground "black" :background "yellow") ; selected area
91 '(doom-modeline-buffer-modified :foreground "orange")
92 '(git-gutter-fr:added :foreground "green4" :background "black")
93 '(git-gutter-fr:deleted :foreground "red4" :background "black")
94 '(git-gutter-fr:modified :foreground "orange4" :background "black")
95 '(flycheck-fringe-error :foreground "red")
96 '(flycheck-fringe-warning :foreground "orange")
97 '(flycheck-fringe-info :foreground "purple")
98 '(flycheck-info :underline '(:color "SkyBlue4" :style wave))
99 '(flycheck-warning :underline '(:color "orange" :style wave))
100 '(flycheck-error :underline '(:color "red" :style wave))
101 '(warning :foreground "orange")
102 '(error :foreground "red")
103 '(ivy-minibuffer-match-face-1 :foreground "grey50" :background "black") ; what is between matches
104 '(ivy-minibuffer-match-face-2 :foreground "black" :background "yellow2")
105 '(ivy-minibuffer-match-face-3 :foreground "black" :background "yellow3")
106 '(ivy-minibuffer-match-face-4 :foreground "black" :background "yellow4")
107 ; Violet
108 ;'(haskell-operator-face :foreground "yellow3")
109 ;'(haskell-type-face :foreground "#5a4e82")
110 ;'(haskell-constructor-face :foreground "#8a4f88")
111 ;'(haskell-constructor-face :foreground "#8a4c87")
112 '(haskell-constructor-face :foreground "white" :bold t)
113 ; Almost the same as haskell-constructor-face
114 ; because that pattern does not match on type-contexts correctly
115 '(haskell-type-face :foreground "white" :bold t)
116 '(lsp-face-highlight-read :background "green10")
117 '(lsp-face-highlight-write :background "green10")
118 '(mode-line :background "gray20")
119 '(mode-line-inactive :background "gray5")
120 '(solaire-default-face :background "gray10")
121 '(solaire-mode-line-face :background "gray20")
122 '(solaire-mode-line-inactive-face :background "gray5")
123 '(doom-modeline-project-dir :foreground "DeepSkyBlue" :bold t)
124 ;'(magit-diff-context-highlight :foreground "white" :background "black")
125 '(magit-diff-added-highlight :foreground "green")
126 '(magit-diff-removed-highlight :foreground "red")
127 ;;'(font-lock-comment-face ((t (:foreground "cyan" :italic t :slant oblique))))
128 ;;'(font-lock-comment-delimiter-face ((t (:foreground "cyan"))))
129 ;;'(fringe ((t (:foreground "red" :background "black"))))
130 ;;'(whitespace-indentation ((t (:foreground "gray50" :bold t))))
131 ;;'(whitespace-space ((t (:foreground "black" :bold t))))
132 ;;'(whitespace-tab ((t (:foreground "gray50" :bold t))))
133 ;;'(whitespace-trailing ((t (:foreground "red" :bold t))))
134 ;;'(font-lock-builtin-face ((t (:foreground "yellow" :weight bold))))
135 ;;'(font-lock-keyword-face ((t (:foreground "yellow" :weight bold))))
136 ;;'(font-lock-string-face ((t (:foreground "magenta"))))
137 ;;'(font-lock-variable-name-face ((t (:foreground "SpringGreen3" :weight bold))))
138 ;;'(nix-antiquote-face ((t (:foreground "blue"))))
139 ;;'(mode-line ((t (:background "midnight blue" :box (:line-width 1 :color "blue") :height 1.0))))
140 ;;'(mode-line-inactive ((t (:background "grey30" :foreground "white" :box (:line-width 1 :color "grey30") :weight light :height 1.0))))
141 ;;'(mode-line ((t (:family "Noto Sans" :height 0.9))))
142 ;;'(mode-line-inactive ((t (:family "Noto Sans" :height 0.9))))
143 ;;'(solaire-mode-line-inactive-face ((t (:background "gray10"))))
144 )
145
146 ;; polymode
147 (use-package! polymode)
148 (define-hostmode poly-haskell-hostmode
149 :mode 'haskell-mode)
150 ;; Support org tables in Haskell files
151 (defun pm--org-table-tail-matcher (ahead)
152 (when (re-search-forward "^[^|]" nil t ahead)
153 (cons (match-beginning 0) (match-end 0))))
154 (define-innermode poly-haskell-org-table-innermode
155 :mode 'org-mode
156 :head-matcher "^|.*"
157 :tail-matcher #'pm--org-table-tail-matcher
158 :head-mode 'body
159 :tail-mode 'host)
160 (define-polymode poly-haskell-mode
161 :hostmode 'poly-haskell-hostmode
162 :innermodes '(poly-haskell-org-table-innermode))
163
164 ;; Language Server Protocol
165 (setq ;+lsp-prompt-to-install-server 'quiet
166 ;lsp-enable-file-watchers nil
167 ;lsp-enable-indentation nil
168 ;lsp-enable-on-type-formatting nil
169 ;lsp-enable-symbol-highlighting nil
170 lsp-ui-doc-enable nil ; slow
171 ;lsp-ui-sideline-enable nil ; not anymore useful than flycheck
172 ;lsp-ui-peek-enable t
173 ;lsp-ui-peek-always-show nil
174 ;lsp-ui-flycheck-enable t
175 ;lsp-ui-flycheck-live-reporting t
176 ;; Disable help mouse-overs for mode-line segments (i.e. :help-echo text).
177 ;; They're generally unhelpful and only add confusing visual clutter.
178 mode-line-default-help-echo nil
179 show-help-function nil
180 global-prettify-symbols-mode nil
181 prettify-symbols-mode -1
182 lsp-treemacs-errors-position-params `((side . right))
183 lsp-log-io nil ; Only for debugging
184 )
185
186 ;; The modeline is not useful to me in the popup window.
187 ;; It looks much nicer to hide it.
188 (remove-hook 'emacs-everywhere-init-hooks #'hide-mode-line-mode)
189
190 ;;(remove-hook 'window-setup-hook #'doom-init-theme-h)
191 ;;(add-hook 'after-init-hook #'doom-init-theme-h 'append)
192 ;;(delq! t custom-theme-load-path)
193
194 (setq auto-save-default t ; Nobody likes to loose work, I certainly don't
195 confirm-kill-emacs nil
196 make-backup-files nil
197 password-cache-expiry nil ; I can trust my computers ... can't I?
198 scroll-margin 10
199 ;; scroll-preserve-screen-position 'always ; Don't have `point' jump around
200 truncate-string-ellipsis "…" ; Unicode ellispis are nicer than "...", and also save /precious/ space
201 kill-whole-line t ; Make Ctrl-K remove the whole line, instead of just emptying it
202 undo-limit 80000000 ; Raise undo-limit to 80Mb
203 x-stretch-cursor nil ; Disorienting
204 )
205
206 ;; Debugging
207 ;(setq debug-on-quit t)
208
209 ;; Haskell
210 (setq haskell-process-log nil
211 haskell-interactive-popup-errors nil
212 )
213 (add-hook 'haskell-mode-hook
214 (lambda ()
215 (set (make-local-variable 'company-backends)
216 (append '((company-capf company-dabbrev-code))
217 company-backends))))
218 (define-hostmode poly-haskell-hostmode
219 :mode 'haskell-mode)
220
221 ;; Layout
222 (setq split-height-threshold nil
223 split-width-threshold 160
224 )
225
226 (after! flycheck
227 ; flycheck-error-list-buffer
228 (set-popup-rule! (rx bos "*Flycheck errors*" eos) :side 'right :size 0.45)
229 (add-hook 'flycheck-error-list-mode-hook
230 (lambda () (setq tabulated-list-sort-key (list "Level"))))
231 )
232 ;(add-hook 'flycheck-error-list-after-refresh-hook
233 ; (lambda ()
234 ; (with-selected-window (flycheck-get-error-list-window t)
235 ; (fit-window-to-buffer (flycheck-get-error-list-window t) 30))))
236
237 ;; Completing
238 (add-hook 'after-init-hook 'global-company-mode)
239 ;(setq company-idle-delay nil)
240
241 ;(use-package! ivy
242 ; :defer t
243 ; :bind
244 ; (:map ivy-minibuffer-map
245 ; ("RET" . 'ivy-alt-done)
246 ; ("TAB" . 'ivy-alt-done))
247 ; :init
248 ; (setq ivy-extra-directories nil
249 ; )
250 ; )
251
252 ;(add-hook! 'org-mode-hook #'mixed-pitch-mode)
253 ;(add-hook! 'org-mode-hook #'solaire-mode)
254 ;(setq mixed-pitch-variable-pitch-cursor nil)
255
256 ;(add-hook! org-mode :append
257 ; #'visual-line-mode
258 ; #'variable-pitch-mode)
259
260 (setq doom-modeline-enable-word-count nil)
261
262 (map! "C-x b" #'counsel-buffer-or-recentf
263 "C-x C-b" #'counsel-switch-buffer)
264 (defun recentf-track-visited-file (_prev _curr)
265 (and buffer-file-name
266 (recentf-add-file buffer-file-name)))
267 (after! recentf
268 (add-hook 'switch-buffer-functions #'recentf-track-visited-file))
269
270 ;; Org
271 ; DOC: https://rgoswami.me/posts/org-note-workflow/
272 ; ToStudy: https://github.com/abo-abo/orca
273 ; ToStudy: https://github.com/weirdNox/org-noter
274 ; ToStudy: https://github.com/bastibe/org-journal
275 ; ToStudy: https://orgmode.org/manual/Org-Crypt.html
276 ; DOC: http://www.wouterspekkink.org/academia/writing/tool/doom-emacs/2021/02/27/writing-academic-papers-with-org-mode.html
277 ; DOC: https://jonathanabennett.github.io/blog/2019/05/29/writing-academic-papers-with-org-mode/
278 ; ToStudy: https://github.com/org-roam/org-roam-ui
279 ; ToStudy: https://blog.tecosaur.com/tmio/2021-07-31-citations.html
280 ; ToStudy: https://github.com/jkitchin/org-ref-cite
281 (setq org-directory "~/documents/notes")
282 (setq org-noter-notes-search-path '("~/notes/path/"))
283
284 (after! org
285 (setq org-log-done t
286 org-log-into-drawer t
287 org-special-ctrl-a/e t
288 org-special-ctrl-k t
289 ;org-hide-emphasis-markers t
290 )
291 (add-to-list 'org-capture-templates
292 '("e" "English" table-line ; key, name, type
293 (file "english/vocabulary.org") ; target
294 "|%^{English}|%^{Français}|%^{Registre|Courant|Soutenu|Familier}|"
295 :kill-buffer t))
296 (add-to-list 'org-capture-templates
297 '("x" "Expense" plain
298 (file "compta.org")
299 "\n%(org-read-date) * send %^{Send to} %^{For why}\nExpense:Gifts %^{Amount}\n %^{Currency|EUR|USD|JPY}\n Assets:%^{Account||Personal|Home}"))
300 ;; Firefox and Chrome
301 ;(add-to-list 'org-capture-templates
302 ; `("P" "Protocol" entry ; key, name, type
303 ; (file+headline +org-capture-notes-file "Inbox") ; target
304 ; "* %^{Title}\nSource: %u, %c\n #+BEGIN_QUOTE\n%i\n#+END_QUOTE\n\n\n%?"
305 ; :prepend t ; properties
306 ; :kill-buffer t))
307 ;(add-to-list 'org-capture-templates
308 ; `("L" "Protocol Link" entry
309 ; (file+headline +org-capture-notes-file "Inbox")
310 ; "* %? [[%:link][%(transform-square-brackets-to-round-ones \"%:description\")]]\n"
311 ; :prepend t
312 ; :kill-buffer t))
313 ; )
314 )
315
316 (map! :after counsel :map org-mode-map
317 "C-c l l h" #'counsel-org-link)
318 (after! counsel
319 (setq counsel-outline-display-style 'title))
320
321 ;(after! org-id
322 ; ;; Do not create ID if a CUSTOM_ID exists
323 ; (setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)
324 ; )
325 ;
326 ;(after! org-agenda
327 ; ;; (setq org-agenda-prefix-format
328 ; ;; '((agenda . " %i %-12:c%?-12t% s")
329 ; ;; ;; Indent todo items by level to show nesting
330 ; ;; (todo . " %i %-12:c%l")
331 ; ;; (tags . " %i %-12:c")
332 ; ;; (search . " %i %-12:c")))
333 ; (setq org-agenda-include-diary t)
334 ; )
335 ;
336 ;(use-package! org-roam
337 ; :defer t
338 ; :hook ((after-init . org-roam-mode))
339 ; :custom
340 ; (setq org-roam-directory "~/documents/notes/org-roam")
341 ;
342 ; ;; Let's set up some org-roam capture templates
343 ; (setq org-roam-capture-templates
344 ; '(("d" "default" plain (function org-roam--capture-get-point)
345 ; "%?"
346 ; :file-name "%<%Y-%m-%d-%H%M%S>-${slug}"
347 ; :head "#+title: ${title}\n"
348 ; :unnarrowed t)))
349 ;
350 ; ;; And now we set necessary variables for org-roam-dailies
351 ; (setq org-roam-dailies-capture-templates
352 ; '(("d" "default" entry
353 ; #'org-roam-capture--get-point
354 ; "* %?"
355 ; :file-name "daily/%<%Y-%m-%d>"
356 ; :head "#+title: %<%Y-%m-%d>\n\n")))
357 ; )
358 ;
359 ;(use-package! org-ref
360 ; :after org-roam
361 ; :config
362 ; (setq reftex-default-bibliography bibliography-files
363 ; org-ref-default-bibliography bibliography-files
364 ; org-ref-bibliography-notes "~/documents/notes/org-roam/bibnotes.org" ;; Is this even needed?
365 ; org-ref-notes-directory "~/documents/notes/org-roam"
366 ; org-ref-notes-function 'orb-edit-notes
367 ; ;org-ref-get-pdf-filename-function 'org-ref-get-pdf-filename-helm-bibtex)
368 ; )
369 ;
370 ;(use-package! bibtex-completion
371 ; :defer t
372 ; :config
373 ; (setq bibtex-completion-notes-path "~/documents/notes/org-roam/"
374 ; bibtex-completion-pdf-field "file"
375 ; bibtex-completion-bibliography bibliography-files
376 ; )
377 ;)
378 ;
379 ;(defvar orb-title-format "${author-or-editor-abbrev} (${date}). ${title}."
380 ; "Format of the title to use for `orb-templates'.")
381 ;
382 ;(use-package! org-roam-bibtex
383 ; :after org-roam
384 ; :hook (org-roam-mode . org-roam-bibtex-mode)
385 ; :bind (:map org-mode-map
386 ; (("C-c n a" . orb-note-actions)))
387 ; :config
388 ; (setq orb-preformat-keywords
389 ; '(("citekey" . "=key=") "title" "date" "author-or-editor-abbrev")
390 ; orb-templates
391 ; `(("r" "ref" plain
392 ; (function org-roam-capture--get-point)
393 ; ""
394 ; :file-name "${citekey}"
395 ; :head ,(s-join "\n"
396 ; (list
397 ; (concat "#+TITLE: " orb-title-format)
398 ; "#+ROAM_KEY: ${ref}"
399 ; ""
400 ; "- tags :: "
401 ; ""
402 ; "* Notes"
403 ; ""))
404 ; :unnarrowed t)
405 ; ("n" "ref + noter" plain
406 ; (function org-roam-capture--get-point)
407 ; ""
408 ; :file-name "${citekey}"
409 ; :head ,(s-join "\n"
410 ; (list
411 ; (concat "#+TITLE: " orb-title-format)
412 ; "#+ROAM_KEY: ${ref}"
413 ; ""
414 ; "- tags :: "
415 ; ""
416 ; "* Annotations :noter:"
417 ; ":PROPERTIES:"
418 ; ":NOTER_DOCUMENT: %(orb-process-file-field \"${citekey}\")"
419 ; ":NOTER_PAGE:"
420 ; ":END:"
421 ; ""))))))
422 ;
423 ;(map! :after pdf-tools
424 ; :map pdf-view-mode-map
425 ; :gn "q" (lambda ()
426 ; (interactive)
427 ; (if (bound-and-true-p org-noter-doc-mode)
428 ; (org-noter-kill-session)
429 ; (kill-current-buffer)))
430 ; )
431 ;
432 ;(use-package! org-noter
433 ; :after (:any org pdf-view)
434 ; :config
435 ; (setq org-noter-notes-search-path '("~/documents/notes/org-roam")
436 ; org-noter-always-create-frame nil
437 ; )
438 ; )
439
440 ;(setq lsp-lens-mode t)
441 (setq doom-modeline-height 1)
442 (setq doom-modeline-lsp t)
443 ;(setq doom-modeline-minor-modes t)
444 ;(setq lsp-modeline-diagnostics-enable t)
445
446 ;; Indenting
447 (setq-default tab-width 2)
448 (setq indent-tabs-mode nil)
449
450 ;; Searching
451 (global-superword-mode t)
452 ; https://emacs.stackexchange.com/questions/9583/how-to-treat-underscore-as-part-of-the-word
453 (modify-syntax-entry ?_ "w")
454 (defun swiper-all/search-word-at-point ()
455 (interactive)
456 (swiper-all (format "%s" (thing-at-point 'word))))
457 ; Highlight without jumping to the next match
458 ; See: https://emacs.stackexchange.com/questions/52411/evil-star-visualstar-without-moving-the-cursor
459 (defun search-word-at-point ()
460 (interactive)
461 (evil-search (progn (evil-ex-search-word-forward)
462 (evil-ex-search-previous)
463 )))
464 (defun search-unbounded-word-at-point ()
465 (interactive)
466 (evil-search (progn (evil-ex-search-unbounded-word-forward)
467 (evil-ex-search-unbounded-word-previous)
468 )))
469 (setq ivy-case-fold-search-default nil ; case-sensitive search by default
470 )
471 (after! evil
472 ;(general-define-key "C-s" '(counsel-grep-or-swiper :which-key "search"))
473 ;(general-define-key :keymaps '(swiper-map) "C-u" '(lambda () (interactive) (kill-line 0)))
474 ;(general-nvmap "/" '(counsel-grep-or-swiper :which-key "search in buffer"))
475 (evil-define-key 'normal global-map
476 (kbd "/") 'swiper
477 (kbd "C-f") 'swiper-all
478 (kbd "C-/") 'swiper-all/search-word-at-point
479 (kbd "*") 'search-word-at-point
480 (kbd "g*") 'search-unbounded-word-at-point
481 )
482 )
483
484 ;; Edition
485 (after! evil
486 (setq evil-want-fine-undo t
487 )
488 (customize-set-variable 'evil-want-Y-yank-to-eol nil)
489 (evil-define-key 'normal global-map (kbd "K") 'evil-join)
490 (evil-define-key 'insert global-map (kbd "C-u") '(lambda () (interactive) (kill-line 0)))
491 (evil-define-key 'normal global-map (kbd "SPC g d") 'git-gutter:popup-hunk)
492 )
493 (setq +vc-gutter-default-style nil
494 )
495 (customize-set-variable 'git-gutter:update-interval 2)
496 ;(customize-set-variable 'git-gutter:window-width 2)
497 (after! git-gutter-fringe
498 (require 'fringe-helper)
499 ; Narrower vertical bar, matching the one in the "+" of git-gutter-fr:added
500 (fringe-helper-define 'git-gutter-fr:modified nil
501 "...XX..."
502 "...XX..."
503 ".XXXXXX."
504 ".XXXXXX."
505 "...XX..."
506 "...XX..."
507 ".XXXXXX."
508 ".XXXXXX.")
509 ; Narrower horizontql bar, matching the one in the "+" of git-gutter-fr:added
510 (fringe-helper-define 'git-gutter-fr:deleted nil
511 "........"
512 "........"
513 "........"
514 ".XXXXXX."
515 ".XXXXXX."
516 "........"
517 "........"
518 "........")
519 )
520
521
522 ;; Folding
523 (defun set-selective-display/at-point (&optional level)
524 "Fold text indented same of more than the cursor.
525 If level is set, set the indent level to LEVEL.
526 If 'selective-display' is already set to LEVEL,
527 calling it again will unset 'selective-display' by setting it to 0."
528 (interactive "P")
529 (if (eq selective-display (1+ (current-column)))
530 (set-selective-display 0)
531 (set-selective-display (or level (1+ (current-column))))))
532 (after! evil
533 (evil-define-key 'normal global-map
534 (kbd "C-d") 'set-selective-display/at-point)
535 )
536 ;; Navigation
537 ;; DOC: https://github.com/noctuid/evil-guide
538 (after! evil
539 (setq evil-cross-lines t
540 evil-move-cursor-back nil
541 evil-search-wrap nil
542 evil-want-C-i-jump nil
543 )
544
545 ;; Switching buffers
546 (evil-define-key 'motion 'global
547 (kbd "<C-i>") 'evil-prev-buffer ; Does not work without the angles ('<' and '>')
548 (kbd "C-k") 'evil-next-buffer
549 )
550 ;(define-key evil-normal-state-map [tab] 'evil-prev-buffer)
551
552 ;; Jumping
553 (evil-define-key 'motion 'global
554 (kbd "C-u") 'better-jumper-jump-backward
555 (kbd "C-o") 'better-jumper-jump-forward
556 )
557
558 ;; Moving with ijkl (instead of hjkl)
559 (evil-define-key '(motion normal visual) 'global
560 (kbd "i") 'evil-previous-visual-line
561 (kbd "j") 'evil-backward-char
562 (kbd "k") 'evil-next-visual-line
563 (kbd "h") 'evil-insert
564 )
565
566 ;; Switching windows with SPC-w + ijkl (instead of hjkl)
567 (define-key evil-window-map "i" 'evil-window-up)
568 (define-key evil-window-map "I" 'evil-window-move-very-top)
569 (define-key evil-window-map "j" 'evil-window-left)
570 (define-key evil-window-map "J" 'evil-window-move-far-left)
571 (define-key evil-window-map "k" 'evil-window-down)
572 (define-key evil-window-map "K" 'evil-window-move-very-bottom)
573 ;(define-key evil-emacs-state-map "\C-w" 'evil-window-map)
574 ;;(evil-define-key 'window global-map "l" 'evil-window-right)
575 ;;(evil-define-key 'window global-map "L" 'evil-window-move-far-right)
576
577 ;; ijkl in Dired
578 ;;(evil-define-key 'normal dired-mode-map "i" 'evil-previous-line)
579
580 ;; Errors
581 (evil-define-key 'motion 'global
582 (kbd "C-j") 'previous-error
583 (kbd "C-l") 'next-error
584 )
585 ;(bind-key "C-j" #'previous-error)
586 ;(bind-key "C-l" #'next-error)
587 )
588 (after! auto-yasnippet
589 (evil-define-key '(motion normal) 'global
590 (kbd "C-<tab>") 'evil-switch-to-windows-last-buffer
591 )
592 )
593 (after! (evil magit evil-collection-magit)
594 (evil-define-key '(motion normal) magit-mode-map
595 (kbd "C-i") 'evil-prev-buffer
596 (kbd "i") 'evil-previous-visual-line
597 (kbd "k") 'evil-next-visual-line
598 (kbd "C-k") 'evil-next-buffer
599 (kbd "j") 'magit-section-backward
600 (kbd "l") 'magit-section-forward
601 )
602 )
603 (after! (evil magit git-rebase)
604 (evil-define-key '(motion normal) git-rebase-mode-map
605 (kbd "C-i") 'evil-prev-buffer
606 (kbd "i") 'evil-previous-visual-line
607 (kbd "k") 'evil-next-visual-line
608 (kbd "C-k") 'evil-next-buffer
609 (kbd "j") 'evil-backward-char
610 )
611 )
612 ;;(eval-after-load 'evil ; to run after evil-integration.el
613 ;; '(progn
614 ;; (define-key Buffer-menu-mode-map "\C-i" 'evil-prev-buffer)
615 ;; (define-key Buffer-menu-mode-map "\C-k" 'evil-next-buffer)
616 ;; (define-key messages-buffer-mode-map "\C-i" 'evil-prev-buffer)
617 ;; (define-key messages-buffer-mode-map "\C-k" 'evil-next-buffer)
618 ;; (define-key completion-list-mode-map "\C-i" 'evil-prev-buffer)
619 ;; (define-key completion-list-mode-map "\C-k" 'evil-next-buffer)
620 ;; ;(define-key custom-theme-mode-map "\C-i" 'evil-prev-buffer)
621 ;; ;(define-key custom-theme-mode-map "\C-k" 'evil-next-buffer)
622 ;; )
623 ;; )
624
625 ;;(with-eval-after-load 'evil-maps
626 ;; (define-key evil-motion-state-map (kbd "TAB") nil))
627
628 ;; Feed reader
629 ; See also: Managing ArXiv RSS Feeds in Emacs https://cundy.me/post/elfeed/
630
631 (setq
632 elfeed-enable-web-interface t
633 url-queue-timeout 30
634 )
635 ;(global-set-key (kbd "C-x w") 'elfeed)
636
637 (defun elfeed-mark-all-as-read ()
638 (interactive)
639 (mark-whole-buffer)
640 (elfeed-search-untag-all-unread))
641
642 ; Functions to support syncing .elfeed between machines
643 ; makes sure elfeed reads index from disk before launching
644 (defun elfeed-load-db-and-open ()
645 "Wrapper to load the elfeed db from disk before opening"
646 (interactive)
647 (elfeed-db-load)
648 (elfeed)
649 (elfeed-search-update--force))
650
651 ; Write to disk when quiting
652 (defun elfeed-save-db-and-bury ()
653 "Wrapper to save the elfeed db to disk before burying buffer"
654 (interactive)
655 (elfeed-db-save)
656 (quit-window))
657
658 (defun elfeed-toggle-star ()
659 "Toggle star"
660 (interactive)
661 (elfeed-search-tag-all '*)
662 )
663 (after! (evil elfeed evil-collection-elfeed)
664 (evil-define-key 'motion elfeed-search-mode-map "m" #'elfeed-toggle-star)
665 )
666
667 (defun elfeed-org-update-incremental ()
668 "Automatically update the feeds from feeds.org when updated"
669 (setq my-elfeed-org-last (or (and (boundp 'elfeed-feeds) elfeed-feeds) nil))
670 (elfeed)
671 (setq my-elfeed-org-current elfeed-feeds)
672 (let ((elfeed-feeds (-difference my-elfeed-org-current my-elfeed-org-last)))
673 ;; You don't need the line below if you don't want to see a message about what feeds are being updated
674 (message "%s" elfeed-feeds)
675 (mapc #'elfeed-update-feed (elfeed--shuffle (elfeed-feed-list))))
676 (setq elfeed-feeds my-elfeed-org-current))
677