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 "-misc-fixed-medium-r-semicondensed--13-120-75-75-c-60-iso10646-1"))
138 (set-frame-font font nil t)
139 (add-to-list 'default-frame-alist `(font . ,font)))
141 ;; fix the emojis too
142 (set-fontset-font t 'emoji '("Noto Emoji" . "iso10646-1")
143 nil 'prepend)
145 ;; some cool stuff
146 (save-place-mode +1)
147 (savehist-mode +1)
148 (setq history-delete-duplicates t
149 history-length 1000
150 savehist-save-minibuffer-history t)
151 (electric-pair-mode +1)
153 (when (boundp #'electric-quote-mode)
154 (electric-quote-mode +1)
155 (setq electric-quote-comment nil))
157 (define-key global-map (kbd "M-/") #'hippie-expand)
158 (setq hippie-expand-try-functions-list
159 '(try-expand-dabbrev
160 try-expand-dabbrev-all-buffers
161 try-expand-dabbrev-from-kill
162 try-complete-file-name-partially
163 try-complete-file-name
164 try-expand-all-abbrevs
165 try-expand-list
166 try-expand-line
167 try-complete-lisp-symbol-partially
168 try-complete-lisp-symbol))
170 (setq isearch-lazy-count t
171 search-whitespace-regexp ".*?"
172 isearch-allow-scroll 'unlimited)
174 (defun op/buffer-to-side-window (place)
175 "Place the current buffer in the side window at PLACE."
176 (interactive (list (intern
177 (completing-read "Which side: "
178 '(top left right bottom)))))
179 (let ((buf (current-buffer)))
180 (display-buffer-in-side-window
181 buf `((window-height . 0.15)
182 (side . ,place)
183 (slot . -1)
184 (window-parameters . ((no-delete-other-windows . t)))))
185 (delete-window)))
187 (defun op/visit-new-migration-file (name)
188 "Visit a new SQL migration file named after NAME."
189 (interactive "Mname: ")
190 (let* ((name (replace-regexp-in-string " " "-" (string-trim name)))
191 (f (format "%s-%s.sql"
192 (format-time-string "%Y%m%d%H%M")
193 name)))
194 (find-file f)))
196 (defun op/fill-or-unfill (fn &optional justify region)
197 "Meant to be an adviced :around `fill-paragraph'.
198 FN is the original `fill-column'. If `last-command' is
199 `fill-paragraph', unfill it, fill it otherwise. Inspired from a
200 post on endless parentheses. Optional argument JUSTIFY and
201 REGION are passed to `fill-paragraph'."
202 (let ((fill-column
203 (if (eq last-command 'fill-paragraph)
204 (progn (setq this-command nil)
205 (point-max))
206 fill-column)))
207 (funcall fn justify region)))
208 (advice-add 'fill-paragraph :around #'op/fill-or-unfill)
210 (defmacro op/deftranspose (name scope key doc)
211 "Macro to produce transposition functions.
212 NAME is the function's symbol. SCOPE is the text object to
213 operate on. Optional DOC is the function's docstring.
215 Transposition over an active region will swap the object at
216 mark (region beginning) with the one at point (region end).
218 It can optionally define a key for the defined function in the
219 `global-map' if KEY is passed.
221 Originally from protesilaos' dotemacs."
222 (declare (indent defun))
223 `(progn
224 (defun ,name (arg)
225 ,doc
226 (interactive "p")
227 (let ((x (intern (format "transpose-%s" ,scope))))
228 (if (use-region-p)
229 (funcall x 0)
230 (funcall x arg))))
231 ,(when key
232 `(define-key global-map (kbd ,key) #',name))))
234 (op/deftranspose op/transpose-lines "lines" "C-x C-t"
235 "Transpose lines or swap over active region.")
237 (op/deftranspose op/transpose-paragraphs "paragraphs" "C-S-t"
238 "Transpose paragraph or swap over active region.")
240 (op/deftranspose op/transpose-sentences "sentences" "C-x M-t"
241 "Transpose sentences or swap over active region.")
243 (op/deftranspose op/transpose-sexps "sexps" "C-M-t"
244 "Transpose sexps or swap over active region.")
246 (op/deftranspose op/transpose-words "words" "M-t"
247 "Transpose words or swap over active region.")
249 (defun op/narrow-or-widen-dwim (p)
250 "Widen if the buffer is narrowed, narrow-dwim otherwise.
251 Dwim means: region, org-src-block, org-subtree or defun,
252 whichever applies first. Narrowing to org-src-blocks actually
253 calls `org-edit-src-code'.
255 With prefix P, don't widen, just narrow even if buffer is already
256 narrowed. With P being -, narrow to page instead of to defun.
258 Taken from endless parentheses."
259 (interactive "P")
260 (declare (interactive-only))
261 (cond ((and (buffer-narrowed-p) (not p)) (widen))
262 ((region-active-p)
263 (narrow-to-region (region-beginning)
264 (region-end)))
265 ((derived-mode-p 'org-mode)
266 ;; `org-edit-src-code' isn't a real narrowing
267 (cond ((ignore-errors (org-edit-src-code) t))
268 ((ignore-errors (org-narrow-to-block) t))
269 (t (org-narrow-to-subtree))))
270 ((eql p '-) (narrow-to-page))
271 (t (narrow-to-defun))))
273 (define-key global-map (kbd "C-c w") #'op/narrow-or-widen-dwim)
275 (with-eval-after-load 'dired
276 (add-hook 'dired-mode-hook #'dired-hide-details-mode)
277 (add-hook 'dired-mode-hook #'dired-omit-mode)
279 (define-key dired-mode-map (kbd "C-c w") #'wdired-change-to-wdired-mode)
281 (require 'dired-x)
282 (setq dired-listing-switches "-lahF"
283 dired-dwim-target t
284 dired-deletion-confirmer #'y-or-n-p
285 dired-do-revert-buffer t))
287 ;; just like telescope!
288 (with-eval-after-load 'diff-mode
289 (define-key diff-mode-map (kbd "M-SPC") #'scroll-down-command))
291 (with-eval-after-load 'elisp-mode
292 (add-hook 'emacs-lisp-mode-hook #'checkdoc-minor-mode)
293 (add-hook 'emacs-lisp-mode-hook #'prettify-symbols-mode)
294 (let ((map emacs-lisp-mode-map))
295 (define-key map (kbd "C-c C-k") #'eval-buffer)
296 (define-key map (kbd "C-c k") #'op/ert-all)
297 (define-key map (kbd "C-c C-z") #'op/ielm-repl)))
299 (with-eval-after-load 'help
300 (add-hook 'help-mode-hook #'visual-line-mode))
302 ;; add melpa
303 (add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/") t)
305 ;; packages that i want to be installed
306 (dolist (pkg '(vc-got eglot sly cider go-mode web-mode lua-mode
307 markdown-mode yaml-mode gemini-mode
308 form-feed shackle puni orderless))
309 (unless (package-installed-p pkg)
310 (message "Installing %s" pkg)
311 (package-install pkg)))
313 (global-form-feed-mode +1)
315 (add-hook 'text-mode-hook #'puni-mode)
316 (add-hook 'prog-mode-hook #'puni-mode)
317 (define-key puni-mode-map (kbd "C-)") #'puni-slurp-forward)
318 (define-key puni-mode-map (kbd "C-(") #'puni-barf-forward)
320 ;;(setq completion-styles '(basic substring initials flex partial-completion))
321 (setq completion-styles '(orderless basic)
322 completion-category-overrides '((file (styles basic partial-completion))))
324 (setq completions-detailed t)
326 (with-eval-after-load 'cider
327 (define-key cider-repl-mode-map (kbd "C-c M-o") #'cider-repl-clear-buffer))
329 (with-eval-after-load 'go-mode
330 (add-hook 'go-mode-hook #'subword-mode))
332 (with-eval-after-load 'eglot
333 (define-key eglot-mode-map (kbd "<f1>") #'eglot-code-actions)
334 (define-key eglot-mode-map (kbd "<f2>") #'eglot-format)
335 (add-to-list 'eglot-ignored-server-capabilites
336 :documentHighlightProvider)
337 (add-to-list 'eglot-server-programs
338 '(c-mode . ("clangd" "--header-insertion=never"))))
340 (add-hook 'emacs-lisp-mode #'nameless-mode)
341 (with-eval-after-load 'nameless
342 (setq nameless-private-prefix t
343 nameless-affect-indentation-and-filling nil)
344 (define-key emacs-lisp-mode-map (kbd "_") #'nameless-insert-name-or-self-insert))
346 (add-to-list 'auto-mode-alist '("\\.html\\'" . web-mode))
347 (with-eval-after-load 'web-mode
348 (setq web-mode-markup-indent-offset 2
349 web-mode-css-indent-offset 2
350 web-mode-style-padding 0
351 web-mode-enable-engine-detection t)
352 (add-hook 'web-mode-hook #'op/disable-tabs)
354 ;; fix .dir-locals.el
355 (defun op/web-mode-fix-dir-locals ()
356 (when (derived-mode-p major-mode 'web-mode)
357 (web-mode-guess-engine-and-content-type)))
358 (add-hook 'hack-local-variables-hook #'op/web-mode-fix-dir-locals)
360 (setq web-mode-enable-auto-pairing nil))
362 (with-eval-after-load 'css-mode
363 (add-hook 'css-mode-hook #'op/disable-tabs))
365 (with-eval-after-load 'flymake
366 (define-key prog-mode-map (kbd "C-c ! n") #'flymake-goto-next-error)
367 (define-key prog-mode-map (kbd "C-c ! p") #'flymake-goto-prev-error))
369 (with-eval-after-load 'cc-mode
370 (setq c-basic-offset 8
371 c-default-style "K&R")
372 (dolist (hook '(c-mode-hook c++-mode-hook))
373 (add-hook hook #'abbrev-mode)
374 (add-hook hook #'subword-mode))
375 (defun op/c-indent ()
376 (interactive)
377 (c-set-offset 'arglist-intro '+)
378 (c-set-offset 'arglist-cont-nonempty '*)
379 (c-set-offset 'label 1))
380 (add-hook 'c-mode-hook #'op/c-indent)
381 ;; TODO: improve it!
382 (defun op/c-add-include (path &optional localp)
383 "Include PATH at the start of the file.
384 If LOCALP is non-nil, the include will be \"local\"."
385 (interactive "Mheader to include: \nP")
386 (save-excursion
387 (let ((re (if localp
388 "^#[ \t]*include[ \t]*\""
389 "^#[ \t]*include[ \t]*<"))
390 (ignore-re "^#include \"compat.h\"")
391 start)
392 (goto-char (point-min))
393 (while (not (or (and (looking-at re)
394 (not (looking-at ignore-re)))
395 (eobp)))
396 (forward-line))
397 (when (eobp)
398 (error "Don't know where to insert the header"))
399 (open-line 1)
400 (insert "#include " (if localp "\"\"" "<>"))
401 (backward-char)
402 (insert path)
403 (move-beginning-of-line 1)
404 (setq start (point))
405 (forward-line)
406 (while (and (looking-at re)
407 (not (eobp)))
408 (forward-line))
409 (sort-lines nil start (point)))))
410 (define-key c-mode-map (kbd "C-c C-a") #'op/c-add-include))
412 (with-eval-after-load 'perl-mode
413 (setq perl-indent-level 8))
415 (with-eval-after-load 'sh-script
416 (setq sh-basic-offset 8
417 sh-indent-after-loop-construct 8
418 sh-indent-after-continuation nil))
422 (setq eshell-hist-ignoredups t)
424 (defun op/eshell-bufname (dir)
425 (concat "*eshell " (expand-file-name dir) "*"))
427 (defun op/eshell (arg)
428 "Run or jump to eshell in current project.
429 If called with prefix argument ARG always create a new eshell
430 buffer."
431 (interactive "P")
432 (let* ((proj (project-current))
433 (dir (if (and proj (not arg))
434 (project-root proj)
435 default-directory))
436 (default-directory dir)
437 (eshell-buffer-name (let ((name (op/eshell-bufname dir)))
438 (if arg
439 (generate-new-buffer name)
440 name))))
441 (eshell)))
442 (define-key global-map (kbd "C-c e") #'op/eshell)
444 (with-eval-after-load 'eshell
445 (setq eshell-save-history-on-exit t
446 eshell-history-size 1024
448 eshell-compl-dir-ignore
449 "\\`\\(\\.\\.?\\|CVS\\|\\.svn\\|\\.git\\|\\.got\\)/\\'")
451 (defun op/eshell-after-cd (&rest _)
452 (rename-buffer (op/eshell-bufname default-directory) t))
454 (advice-add #'eshell/cd :after #'op/eshell-after-cd))
456 (with-eval-after-load 'esh-mode
457 (defun op/clear-eshell ()
458 (interactive "")
459 (let ((inhibit-read-only t))
460 (erase-buffer)
461 (eshell-send-input)))
463 (define-key eshell-command-map (kbd "M-o") #'op/clear-eshell))
466 ;; sndio.el
467 (unless (package-installed-p 'sndio)
468 (package-install-file "~/w/sndio.el/sndio.el"))
471 ;; saturn
472 (unless (package-installed-p 'saturn)
473 (package-install-file "~/w/saturn/GUI/saturn.el"))
476 ;; emacs-pq
477 (add-to-list 'load-path "~/build/emacs-libpq/")
478 (unless (package-installed-p 'pq)
479 (package-install-file "~/build/emacs-libpq/pq.el"))
482 ;; plass
483 (unless (package-installed-p 'plass)
484 (ignore-errors
485 (package-install-file "~/w/plass/plass.el")))
487 (with-eval-after-load 'plass
488 (setq plass-filter "!2fa"
489 plass-totp-filter "2fa"))
493 (setq shackle-default-rule nil
494 shackle-rules
495 (let ((repls "\\*\\(cider-repl\\|sly-mrepl\\|ielm\\)")
496 (godot "\\*godot - .*\\*")
497 (vcs "\\*\\(Flymake\\|Package-Lint\\|vc-\\(git\\|got\\) :\\).*")
498 (elfeed "\\*elfeed-entry\\*")
499 (vmd "\\*vmd console .*"))
500 `(("*Async Shell Command*" :ignore t)
501 (,repls :regexp t
502 :align below
503 :size 0.3)
504 (,godot :regexp t
505 :align t
506 :size 0.3)
507 (occur-mode :select t
508 :align right
509 :size 0.3)
510 (diff-mode :select t)
511 (help-mode :select t
512 :align left
513 :size 0.3)
514 (,vcs :regexp t
515 :align above
516 :size 0.15
517 :select t)
518 (,elfeed :regexp t
519 :align t
520 :select t
521 :size 0.75)
522 (,vmd :regexp t
523 :align below
524 :select t
525 :size 0.3))))
526 (shackle-mode +1)
528 ;; (setq display-buffer-alist nil)