Blob


1 ;; get rid of custom from my init file
2 (setq custom-file "~/.emacs.d/emacs-custom.el")
3 (load custom-file)
5 (setq-default abbrev-mode t)
6 (setq abbrev-file-name
7 (expand-file-name "~/dotsnew/emacs/abbrev_defs"))
9 (defconst op/backup-dir
10 (expand-file-name "backups" user-emacs-directory))
11 (unless (file-exists-p op/backup-dir)
12 (make-directory op/backup-dir))
13 (setq backup-directory-alist `(("." . ,op/backup-dir)))
15 (setq use-dialog-box nil
16 x-stretch-cursor t
17 require-final-newline t
18 visible-bell nil
19 load-prefer-newer t
20 tab-bar-show 1
21 enable-recursive-minibuffers t
22 imenu-auto-rescan 1
23 use-short-answers t
24 next-error-message-highlight t
25 read-minibuffer-restore-windows nil
26 isearch-allow-motion t
27 calc-make-windows-dedicated t
28 user-mail-address "op@omarpolo.com")
30 (setq completion-ignore-case t
31 read-file-name-completion-ignore-case t
32 read-buffer-completion-ignore-case t)
34 ;; I don't like how compile uses `make -k' by default, I want to stop
35 ;; on errors / warnings.
36 (setq compile-command "make")
38 ;; "diff refinement", i.e. highlighting the changes in a more granular
39 ;; way, is quite awful to have it enabled by default. sometimes is
40 ;; useful, but for me it's more of a visual noise most of the times.
41 (setq diff-refine nil)
43 ;; disable also the syntax highlighting in the diff buffers
44 (setq diff-font-lock-syntax nil)
46 (define-key global-map (kbd "C-x C-b") #'ibuffer)
47 (define-key global-map (kbd "M-g i") #'imenu)
49 (defun op/imenu ()
50 "Just like `imenu', but always flattened!"
51 (interactive ))
53 ;; mg-like
54 (define-key minibuffer-mode-map (kbd "C-w") #'backward-kill-word)
56 ;; niceties for the standard completion
57 (setq completion-auto-help 'always
58 completion-auto-select 'second-tab
59 completions-max-height 10
60 completions-format 'horizontal
61 completions-header-format ""
62 completion-show-help nil)
64 (define-key minibuffer-local-map (kbd "C-p") #'minibuffer-previous-completion)
65 (define-key minibuffer-local-map (kbd "C-n") #'minibuffer-next-completion)
67 (define-key completion-in-region-mode-map (kbd "C-p")
68 #'minibuffer-previous-completion)
69 (define-key completion-in-region-mode-map (kbd "C-n")
70 #'minibuffer-next-completion)
72 (define-key completion-in-region-mode-map (kbd "M-RET")
73 #'minibuffer-choose-completion)
75 (defun op/reverse-other-window ()
76 "Like `other-window', but reverse."
77 (interactive "")
78 (other-window -1))
79 (define-key global-map (kbd "C-x O") #'op/reverse-other-window)
81 (define-key global-map (kbd "C-x v f") #'vc-pull)
83 (setq uniquify-buffer-name-style 'forward
84 uniquify-strip-common-suffix t)
86 (setq-default scroll-up-aggressively 0.0
87 scroll-down-aggressively 0.0
88 scroll-preserve-screen-position t
89 next-screen-context-lines 1)
91 (define-key global-map (kbd "M-Z") #'zap-up-to-char)
93 (require 'whitespace)
94 (setq whitespace-style '(face trailing)
95 backward-delete-char-untabify-method 'hungry
96 tab-always-indent 'complete
97 tab-width 8
98 sentence-end-double-space t)
99 (setq-default indent-tabs-mode t)
101 (defun op/enable-tabs ()
102 "Enable `indent-tabs-mode' in the current buffer."
103 (interactive)
104 (setq-local indent-tabs-mode t))
106 (defun op/disable-tabs ()
107 "Disable `indent-tabs-mode' in the current buffer."
108 (interactive)
109 (setq-local indent-tabs-mode nil))
111 (add-hook 'conf-mode-hook #'op/enable-tabs)
112 (add-hook 'text-mode-hook #'op/enable-tabs)
113 (add-hook 'prog-mode-hook #'op/enable-tabs)
114 (add-hook 'prog-mode-hook #'whitespace-mode)
115 (add-hook 'text-mode-hook #'whitespace-mode)
117 (dolist (hook '(emacs-lisp-mode-hook
118 clojure-mode-hook
119 clojurescript-mode-hook
120 clojurec-mode-hook
121 scss-mode-hook))
122 (add-hook hook #'op/disable-tabs))
124 (with-eval-after-load 'log-edit
125 (add-hook 'log-edit-mode #'auto-fill-mode))
127 ;; free the c-z binding
128 (define-key global-map (kbd "C-z") nil)
129 (define-key global-map (kbd "C-z V") #'variable-pitch-mode)
130 (define-key global-map (kbd "C-z n") #'display-line-numbers-mode)
132 (define-key global-map (kbd "M-SPC") #'cycle-spacing)
133 (define-key global-map (kbd "M-u") #'upcase-dwim)
134 (define-key global-map (kbd "M-l") #'downcase-dwim)
135 (define-key global-map (kbd "M-c") #'capitalize-dwim)
137 (let ((font
138 ;; "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1"
139 "JuliaMono 8"
140 ))
141 (set-frame-font font nil t)
142 (add-to-list 'default-frame-alist `(font . ,font)))
144 ;; fix the emojis too
145 (set-fontset-font t 'emoji '("Noto Emoji" . "iso10646-1")
146 nil 'prepend)
148 ;; some cool stuff
149 (save-place-mode +1)
150 (savehist-mode +1)
151 (setq history-delete-duplicates t
152 history-length 1000
153 savehist-save-minibuffer-history t)
154 (electric-pair-mode +1)
156 (when (boundp #'electric-quote-mode)
157 (electric-quote-mode +1)
158 (setq electric-quote-comment nil))
160 (define-key global-map (kbd "M-/") #'hippie-expand)
161 (setq hippie-expand-try-functions-list
162 '(try-expand-dabbrev
163 try-expand-dabbrev-all-buffers
164 try-expand-dabbrev-from-kill
165 try-complete-file-name-partially
166 try-complete-file-name
167 try-expand-all-abbrevs
168 try-expand-list
169 try-expand-line
170 try-complete-lisp-symbol-partially
171 try-complete-lisp-symbol))
173 (setq isearch-lazy-count t
174 search-whitespace-regexp ".*?"
175 isearch-allow-scroll 'unlimited)
177 (defun op/buffer-to-side-window (place)
178 "Place the current buffer in the side window at PLACE."
179 (interactive (list (intern
180 (completing-read "Which side: "
181 '(top left right bottom)))))
182 (let ((buf (current-buffer)))
183 (display-buffer-in-side-window
184 buf `((window-height . 0.15)
185 (side . ,place)
186 (slot . -1)
187 (window-parameters . ((no-delete-other-windows . t)))))
188 (delete-window)))
190 (defun op/visit-new-migration-file (name)
191 "Visit a new SQL migration file named after NAME."
192 (interactive "Mname: ")
193 (let* ((name (replace-regexp-in-string " " "-" (string-trim name)))
194 (f (format "%s-%s.sql"
195 (format-time-string "%Y%m%d%H%M")
196 name)))
197 (find-file f)))
199 (defun op/fill-or-unfill (fn &optional justify region)
200 "Meant to be an adviced :around `fill-paragraph'.
201 FN is the original `fill-column'. If `last-command' is
202 `fill-paragraph', unfill it, fill it otherwise. Inspired from a
203 post on endless parentheses. Optional argument JUSTIFY and
204 REGION are passed to `fill-paragraph'."
205 (let ((fill-column
206 (if (eq last-command 'fill-paragraph)
207 (progn (setq this-command nil)
208 (point-max))
209 fill-column)))
210 (funcall fn justify region)))
211 (advice-add 'fill-paragraph :around #'op/fill-or-unfill)
213 (defmacro op/deftranspose (name scope key doc)
214 "Macro to produce transposition functions.
215 NAME is the function's symbol. SCOPE is the text object to
216 operate on. Optional DOC is the function's docstring.
218 Transposition over an active region will swap the object at
219 mark (region beginning) with the one at point (region end).
221 It can optionally define a key for the defined function in the
222 `global-map' if KEY is passed.
224 Originally from protesilaos' dotemacs."
225 (declare (indent defun))
226 `(progn
227 (defun ,name (arg)
228 ,doc
229 (interactive "p")
230 (let ((x (intern (format "transpose-%s" ,scope))))
231 (if (use-region-p)
232 (funcall x 0)
233 (funcall x arg))))
234 ,(when key
235 `(define-key global-map (kbd ,key) #',name))))
237 (op/deftranspose op/transpose-lines "lines" "C-x C-t"
238 "Transpose lines or swap over active region.")
240 (op/deftranspose op/transpose-paragraphs "paragraphs" "C-S-t"
241 "Transpose paragraph or swap over active region.")
243 (op/deftranspose op/transpose-sentences "sentences" "C-x M-t"
244 "Transpose sentences or swap over active region.")
246 (op/deftranspose op/transpose-sexps "sexps" "C-M-t"
247 "Transpose sexps or swap over active region.")
249 (op/deftranspose op/transpose-words "words" "M-t"
250 "Transpose words or swap over active region.")
252 (defun op/narrow-or-widen-dwim (p)
253 "Widen if the buffer is narrowed, narrow-dwim otherwise.
254 Dwim means: region, org-src-block, org-subtree or defun,
255 whichever applies first. Narrowing to org-src-blocks actually
256 calls `org-edit-src-code'.
258 With prefix P, don't widen, just narrow even if buffer is already
259 narrowed. With P being -, narrow to page instead of to defun.
261 Taken from endless parentheses."
262 (interactive "P")
263 (declare (interactive-only))
264 (cond ((and (buffer-narrowed-p) (not p)) (widen))
265 ((region-active-p)
266 (narrow-to-region (region-beginning)
267 (region-end)))
268 ((derived-mode-p 'org-mode)
269 ;; `org-edit-src-code' isn't a real narrowing
270 (cond ((ignore-errors (org-edit-src-code) t))
271 ((ignore-errors (org-narrow-to-block) t))
272 (t (org-narrow-to-subtree))))
273 ((eql p '-) (narrow-to-page))
274 (t (narrow-to-defun))))
276 (define-key global-map (kbd "C-c w") #'op/narrow-or-widen-dwim)
278 (with-eval-after-load 'dired
279 (add-hook 'dired-mode-hook #'dired-hide-details-mode)
280 (add-hook 'dired-mode-hook #'dired-omit-mode)
282 (define-key dired-mode-map (kbd "C-c w") #'wdired-change-to-wdired-mode)
284 (require 'dired-x)
285 (setq dired-listing-switches "-lahF"
286 dired-dwim-target t
287 dired-deletion-confirmer #'y-or-n-p
288 dired-do-revert-buffer t))
290 ;; just like telescope!
291 (with-eval-after-load 'diff-mode
292 (define-key diff-mode-map (kbd "M-SPC") #'scroll-down-command))
294 (with-eval-after-load 'elisp-mode
295 (add-hook 'emacs-lisp-mode-hook #'checkdoc-minor-mode)
296 (add-hook 'emacs-lisp-mode-hook #'prettify-symbols-mode)
297 (let ((map emacs-lisp-mode-map))
298 (define-key map (kbd "C-c C-k") #'eval-buffer)
299 (define-key map (kbd "C-c k") #'op/ert-all)
300 (define-key map (kbd "C-c C-z") #'op/ielm-repl)))
302 (with-eval-after-load 'help
303 (add-hook 'help-mode-hook #'visual-line-mode))
305 ;; add melpa
306 (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
308 ;; packages that i want to be installed
309 (dolist (pkg '(vc-got eglot sly cider go-mode web-mode lua-mode
310 markdown-mode yaml-mode gemini-mode
311 form-feed shackle puni orderless))
312 (unless (package-installed-p pkg)
313 (message "Installing %s" pkg)
314 (package-install pkg)))
316 (global-form-feed-mode +1)
318 (add-hook 'text-mode-hook #'puni-mode)
319 (add-hook 'prog-mode-hook #'puni-mode)
320 (define-key puni-mode-map (kbd "C-)") #'puni-slurp-forward)
321 (define-key puni-mode-map (kbd "C-(") #'puni-barf-forward)
323 ;;(setq completion-styles '(basic substring initials flex partial-completion))
324 (setq completion-styles '(orderless basic)
325 completion-category-overrides '((file (styles basic partial-completion))))
327 (setq completions-detailed t)
329 (with-eval-after-load 'cider
330 (define-key cider-repl-mode-map (kbd "C-c M-o") #'cider-repl-clear-buffer))
332 (with-eval-after-load 'go-mode
333 (add-hook 'go-mode-hook #'subword-mode))
335 (with-eval-after-load 'eglot
336 (define-key eglot-mode-map (kbd "<f1>") #'eglot-code-actions)
337 (define-key eglot-mode-map (kbd "<f2>") #'eglot-format)
338 (add-to-list 'eglot-ignored-server-capabilites
339 :documentHighlightProvider)
340 (add-to-list 'eglot-server-programs
341 '(c-mode . ("clangd" "--header-insertion=never"))))
343 (add-hook 'emacs-lisp-mode #'nameless-mode)
344 (with-eval-after-load 'nameless
345 (setq nameless-private-prefix t
346 nameless-affect-indentation-and-filling nil)
347 (define-key emacs-lisp-mode-map (kbd "_") #'nameless-insert-name-or-self-insert))
349 (add-to-list 'auto-mode-alist '("\\.html\\'" . web-mode))
350 (with-eval-after-load 'web-mode
351 (setq web-mode-markup-indent-offset 2
352 web-mode-css-indent-offset 2
353 web-mode-style-padding 0
354 web-mode-enable-engine-detection t)
355 (add-hook 'web-mode-hook #'op/disable-tabs)
357 ;; fix .dir-locals.el
358 (defun op/web-mode-fix-dir-locals ()
359 (when (derived-mode-p major-mode 'web-mode)
360 (web-mode-guess-engine-and-content-type)))
361 (add-hook 'hack-local-variables-hook #'op/web-mode-fix-dir-locals)
363 (setq web-mode-enable-auto-pairing nil))
365 (with-eval-after-load 'css-mode
366 (add-hook 'css-mode-hook #'op/disable-tabs))
368 (with-eval-after-load 'flymake
369 (define-key prog-mode-map (kbd "C-c ! n") #'flymake-goto-next-error)
370 (define-key prog-mode-map (kbd "C-c ! p") #'flymake-goto-prev-error))
372 (with-eval-after-load 'cc-mode
373 (setq c-basic-offset 8
374 c-default-style "K&R")
375 (dolist (hook '(c-mode-hook c++-mode-hook))
376 (add-hook hook #'abbrev-mode)
377 (add-hook hook #'subword-mode))
378 (defun op/c-indent ()
379 (interactive)
380 (c-set-offset 'arglist-intro '+)
381 (c-set-offset 'arglist-cont-nonempty '*)
382 (c-set-offset 'label 1))
383 (add-hook 'c-mode-hook #'op/c-indent)
384 ;; TODO: improve it!
385 (defun op/c-add-include (path &optional localp)
386 "Include PATH at the start of the file.
387 If LOCALP is non-nil, the include will be \"local\"."
388 (interactive "Mheader to include: \nP")
389 (save-excursion
390 (let ((re (if localp
391 "^#[ \t]*include[ \t]*\""
392 "^#[ \t]*include[ \t]*<"))
393 (ignore-re "^#include \"compat.h\"")
394 start)
395 (goto-char (point-min))
396 (while (not (or (and (looking-at re)
397 (not (looking-at ignore-re)))
398 (eobp)))
399 (forward-line))
400 (when (eobp)
401 (error "Don't know where to insert the header"))
402 (open-line 1)
403 (insert "#include " (if localp "\"\"" "<>"))
404 (backward-char)
405 (insert path)
406 (move-beginning-of-line 1)
407 (setq start (point))
408 (forward-line)
409 (while (and (looking-at re)
410 (not (eobp)))
411 (forward-line))
412 (sort-lines nil start (point)))))
413 (define-key c-mode-map (kbd "C-c C-a") #'op/c-add-include))
415 (with-eval-after-load 'perl-mode
416 (setq perl-indent-level 8))
418 (with-eval-after-load 'sh-script
419 (setq sh-basic-offset 8
420 sh-indent-after-loop-construct 8
421 sh-indent-after-continuation nil))
425 (setq eshell-hist-ignoredups t)
427 (defun op/eshell-bufname (dir)
428 (concat "*eshell " (expand-file-name dir) "*"))
430 (defun op/eshell (arg)
431 "Run or jump to eshell in current project.
432 If called with prefix argument ARG always create a new eshell
433 buffer."
434 (interactive "P")
435 (let* ((proj (project-current))
436 (dir (if (and proj (not arg))
437 (project-root proj)
438 default-directory))
439 (default-directory dir)
440 (eshell-buffer-name (let ((name (op/eshell-bufname dir)))
441 (if arg
442 (generate-new-buffer name)
443 name))))
444 (eshell)))
445 (define-key global-map (kbd "C-c e") #'op/eshell)
447 (with-eval-after-load 'eshell
448 (setq eshell-save-history-on-exit t
449 eshell-history-size 1024
451 eshell-compl-dir-ignore
452 "\\`\\(\\.\\.?\\|CVS\\|\\.svn\\|\\.git\\|\\.got\\)/\\'")
454 (defun op/eshell-after-cd (&rest _)
455 (rename-buffer (op/eshell-bufname default-directory) t))
457 (advice-add #'eshell/cd :after #'op/eshell-after-cd))
459 (with-eval-after-load 'esh-mode
460 (defun op/clear-eshell ()
461 (interactive "")
462 (let ((inhibit-read-only t))
463 (erase-buffer)
464 (eshell-send-input)))
466 (define-key eshell-command-map (kbd "M-o") #'op/clear-eshell))
469 ;; sndio.el
470 (unless (package-installed-p 'sndio)
471 (package-install-file "~/w/sndio.el/sndio.el"))
474 ;; saturn
475 (unless (package-installed-p 'saturn)
476 (package-install-file "~/w/saturn/GUI/saturn.el"))
479 ;; emacs-pq
480 (add-to-list 'load-path "~/build/emacs-libpq/")
481 (unless (package-installed-p 'pq)
482 (package-install-file "~/build/emacs-libpq/pq.el"))
485 ;; plass
486 (unless (package-installed-p 'plass)
487 (ignore-errors
488 (package-install-file "~/w/plass/plass.el")))
490 (with-eval-after-load 'plass
491 (setq plass-filter "!2fa"
492 plass-totp-filter "2fa"))
496 (setq shackle-default-rule nil
497 shackle-rules
498 (let ((repls "\\*\\(cider-repl\\|sly-mrepl\\|ielm\\)")
499 (godot "\\*godot - .*\\*")
500 (vcs "\\*\\(Flymake\\|Package-Lint\\|vc-\\(git\\|got\\) :\\).*")
501 (elfeed "\\*elfeed-entry\\*")
502 (vmd "\\*vmd console .*"))
503 `(("*Async Shell Command*" :ignore t)
504 (,repls :regexp t
505 :align below
506 :size 0.3)
507 (,godot :regexp t
508 :align t
509 :size 0.3)
510 (occur-mode :select t
511 :align right
512 :size 0.3)
513 (diff-mode :select t)
514 (help-mode :select t
515 :align left
516 :size 0.3)
517 (,vcs :regexp t
518 :align above
519 :size 0.15
520 :select t)
521 (,elfeed :regexp t
522 :align t
523 :select t
524 :size 0.75)
525 (,vmd :regexp t
526 :align below
527 :select t
528 :size 0.3))))
529 (shackle-mode +1)
531 ;; (setq display-buffer-alist nil)