Files
emacs-doom/config.el
Martin Sukany 52d90e72d8 update
2026-02-07 22:55:15 +01:00

223 lines
8.2 KiB
EmacsLisp
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
;;; $DOOMDIR/config.el -*- lexical-binding: t; -*-
;; --------------------------------------------------
;; Theme / UI
;; --------------------------------------------------
(setq doom-theme 'tango-dark
display-line-numbers-type t
doom-font (font-spec :family "JetBrains Mono" :size 14)
doom-variable-pitch-font nil)
;; --------------------------------------------------
;; macOS / UX
;; --------------------------------------------------
(setq mouse-autoselect-window t
focus-follows-mouse t
select-enable-clipboard t
select-enable-primary t
inhibit-splash-screen t)
;; --------------------------------------------------
;; Completion (Company) minimum, bezpečné
;; --------------------------------------------------
(after! company
(setq company-idle-delay 0.1
company-minimum-prefix-length 2
company-selection-wrap-around t
company-tooltip-limit 14
company-show-numbers t
company-require-match nil)
;; Spolehlivé vyvolání v TTY
(map! :i "C-." #'company-complete
:n "C-." #'company-complete))
;; --------------------------------------------------
;; Robustní file completion "kdekoliv pod kurzorem"
;; --------------------------------------------------
(defun martin/complete-file-name-at-point ()
"Doplň název souboru kolem kurzoru pomocí standardní file completion tabulky.
Funguje v libovolném textu, včetně Markdown linků (např. [x](./...))."
(interactive)
(let* ((stop-chars '(?\s ?\t ?\n ?\r ?\" ?\' ?\( ?\) ?\[ ?\] ?\< ?\> ?\{ ?\} ?, ?\; ))
(start (save-excursion
(while (and (> (point) (point-min))
(let ((c (char-before)))
(and c (not (memq c stop-chars)))))
(backward-char))
(point)))
(end (save-excursion
(while (and (< (point) (point-max))
(let ((c (char-after)))
(and c (not (memq c stop-chars)))))
(forward-char))
(point))))
(when (= start end)
(setq start (point) end (point)))
(let ((completion-category-defaults nil)
(completion-category-overrides '((file (styles basic partial-completion)))))
(completion-in-region start end #'completion-file-name-table))))
(map! :i "C-c f" #'martin/complete-file-name-at-point
:n "C-c f" #'martin/complete-file-name-at-point)
(after! markdown-mode
(add-hook 'markdown-mode-hook (lambda () (setq-local company-minimum-prefix-length 1)))
(add-hook 'gfm-mode-hook (lambda () (setq-local company-minimum-prefix-length 1))))
;; --------------------------------------------------
;; Org
;; --------------------------------------------------
(setq org-directory "~/org/")
(after! org
(setq org-default-notes-file (expand-file-name "inbox.org" org-directory))
(setq org-agenda-files (list org-directory
(expand-file-name "projects" org-directory)
(expand-file-name "notes" org-directory)))
(setq org-todo-keywords
'((sequence "TODO(t)" "NEXT(n)" "WAIT(w@/!)" "|" "DONE(d!)" "CANCELLED(c@)")))
(setq org-log-done 'time)
(setq org-refile-targets '((org-agenda-files :maxlevel . 5))
org-outline-path-complete-in-steps nil
org-refile-use-outline-path 'file)
(defun my/project-org-file ()
"Return path to ./project.org in current Projectile project, if it exists."
(when-let ((root (projectile-project-root)))
(let ((f (expand-file-name "project.org" root)))
(when (file-exists-p f) f))))
(defun my/org-agenda-project ()
"Open Org agenda restricted to current project's project.org."
(interactive)
(let ((org-agenda-files (delq nil (list (my/project-org-file)))))
(if org-agenda-files
(org-agenda nil "a")
(user-error "No project.org found in this project"))))
(setq org-capture-templates
'(("i" "Inbox task" entry
(file "inbox.org")
"* TODO %?\n%U\n%a\n")
("n" "Note" entry
(file+headline "inbox.org" "Notes")
"* %?\n%U\n%a\n")
("p" "Project task" entry
(file "inbox.org")
"* TODO %? :project:\n%U\n%a\n"))))
;; --------------------------------------------------
;; Dired
;; --------------------------------------------------
(after! dired
(put 'dired-find-alternate-file 'disabled nil)
(map! :map dired-mode-map
"RET" #'dired-find-alternate-file
"^" #'dired-up-directory))
;; --------------------------------------------------
;; PlantUML (server)
;; --------------------------------------------------
(add-to-list 'auto-mode-alist '("\\.puml\\'" . plantuml-mode))
(add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode))
(after! plantuml-mode
(setq plantuml-default-exec-mode 'server
plantuml-server-url "https://www.plantuml.com/plantuml"
plantuml-output-type "svg"
plantuml-verbose t))
(defun my/plantuml-encode-hex (text)
"PlantUML HEX encoding: ~h + hex(UTF-8 bytes)."
(let* ((utf8 (encode-coding-string text 'utf-8 t)))
(concat "~h"
(apply #'concat
(mapcar (lambda (b) (format "%02x" b))
(append utf8 nil))))))
(defun my/plantuml-fix-png-header (file)
"Odstraní vše před PNG signaturou."
(let ((sig (unibyte-string #x89 ?P ?N ?G ?\r ?\n #x1a ?\n)))
(with-temp-buffer
(set-buffer-multibyte nil)
(insert-file-contents-literally file)
(goto-char (point-min))
(unless (looking-at (regexp-quote sig))
(let ((pos (search-forward sig nil t)))
(unless pos (user-error "PNG signature nenalezena"))
(delete-region (point-min) (- pos (length sig)))
(let ((coding-system-for-write 'binary))
(write-region (point-min) (point-max) file nil 'silent)))))))
(defun my/plantuml-render-server (type)
"Render aktuální .puml přes PlantUML server do PNG nebo SVG."
(interactive (list (completing-read "Type: " '("png" "svg") nil t "png")))
(unless buffer-file-name (user-error "Otevři .puml jako soubor"))
(let* ((text (buffer-substring-no-properties (point-min) (point-max)))
(encoded (my/plantuml-encode-hex text))
(server (string-remove-suffix "/" plantuml-server-url))
(url (format "%s/%s/%s" server type encoded))
(out (concat (file-name-sans-extension buffer-file-name) "." type)))
(url-copy-file url out t)
(when (string-equal type "png")
(my/plantuml-fix-png-header out))
(message "PlantUML uložen: %s" out)
out))
(after! plantuml-mode
(define-key plantuml-mode-map (kbd "C-c C-p")
(lambda () (interactive) (my/plantuml-render-server "png")))
(define-key plantuml-mode-map (kbd "C-c C-s")
(lambda () (interactive) (my/plantuml-render-server "svg"))))
;; --------------------------------------------------
;; PATH fix for MacTeX
;; --------------------------------------------------
(setenv "PATH" (concat "/Library/TeX/texbin:" (getenv "PATH")))
(add-to-list 'exec-path "/Library/TeX/texbin")
;; --------------------------------------------------
;; Python
;; --------------------------------------------------
(setq python-shell-interpreter "python3")
(after! org
(setq org-babel-python-command "python3")
(require 'ob-python))
;; --------------------------------------------------
;; Low-vision základ
;; --------------------------------------------------
(setq doom-font (font-spec :family "JetBrains Mono" :size 20)
doom-variable-pitch-font (font-spec :family "SF Pro Text" :size 20))
(setq-default line-spacing 0.25)
(map! :n "C-=" #'text-scale-increase
:n "C--" #'text-scale-decrease
:n "C-0" #'text-scale-set
:i "C-=" #'text-scale-increase
:i "C--" #'text-scale-decrease
:i "C-0" #'text-scale-set)
(add-hook 'org-after-refile-insert-hook #'save-buffer)
(add-hook 'org-after-todo-state-change-hook #'save-buffer)
(add-hook 'org-capture-after-finalize-hook #'save-buffer)
(run-with-idle-timer
300 t
(lambda ()
(save-some-buffers t (lambda ()
(derived-mode-p 'org-mode)))))
;; performance tweak
(after! projectile
(setq projectile-indexing-method 'alien
projectile-enable-caching t))