#+begin_src emacs-lisp :comments no ;;; $DOOMDIR/config.el -*- lexical-binding: t; -*- #+end_src * Personal information #+begin_src emacs-lisp (setq user-full-name "Óscar Nájera" user-mail-address "hi@oscarnajera.com") #+end_src * Editor ** Theme #+begin_src emacs-lisp (setq doom-font (font-spec :family "DejaVu Sans Mono" :size 16 :weight 'semi-light)) (setq doom-theme 'doom-gruvbox) #+end_src This determines the style of line numbers in effect. If set to `nil', line numbers are disabled. For relative line numbers, set this to `relative'. #+begin_src emacs-lisp ;(setq display-line-numbers-type 'relative) #+end_src ** Frame title includes file being used #+BEGIN_SRC emacs-lisp ;;http://emacs-fu.blogspot.fr/2011/01/setting-frame-title.html (setq frame-title-format '("" invocation-name ": "(:eval (if (buffer-file-name) (abbreviate-file-name (buffer-file-name)) "%b")))) #+END_SRC ** Keybindings #+begin_src emacs-lisp (map! :leader :desc "M-x" "x" #'execute-extended-command ) #+end_src ** Package Manager Doom manages packages separately. Keep that file separate #+begin_src emacs-lisp :tangle "packages.el" ;; -*- no-byte-compile: t; -*- ;;; $DOOMDIR/packages.el #+end_src ** SSH agent #+begin_src emacs-lisp (setenv "SSH_AUTH_SOCK" (concat (getenv "XDG_RUNTIME_DIR")"/gnupg/S.gpg-agent.ssh")) #+end_src ** Avy This allows me to jump to buffer positions using my home row ordering #+begin_src emacs-lisp (after! avy (setq avy-all-windows t avy-all-windows-alt nil) (setq avy-keys '(?r ?t ?i ?e ?a ?o ?n ?s))) #+end_src ** Ace window #+begin_src emacs-lisp (after! ace-window (global-set-key (kbd "s-w") 'evil-window-map) (setq aw-keys '(?r ?t ?i ?e ?a ?o ?n ?s))) #+end_src ** Which-key Because I always need help and it should come up quickly #+begin_src emacs-lisp (setq which-key-idle-delay 0.1) #+end_src ** Smartparens #+begin_src emacs-lisp (after! smartparens (map! :map smartparens-mode-map :nvie "C-)" #'sp-forward-slurp-sexp :nvie "C-}" #'sp-forward-barf-sexp :nvie "C-(" #'sp-backward-slurp-sexp :nvie "C-{" #'sp-backward-barf-sexp :nie "M-s" #'sp-split-sexp :nie "M-j" #'sp-join-sexp) (map! :map (emacs-lisp-mode-map scheme-mode-map lisp-mode-map clojure-mode-map) :nv ")" #'sp-next-sexp :nv "(" #'sp-backward-sexp)) #+end_src * Dictionary #+begin_src emacs-lisp :tangle "packages.el" (package! lexic) #+end_src Shamelessly copied from https://tecosaur.github.io/emacs-config/#dictionary #+begin_src emacs-lisp (use-package! lexic :commands lexic-search lexic-list-dictionary :config (set-evil-initial-state! 'lexic-mode 'emacs)) #+end_src #+begin_src emacs-lisp (defadvice! +lookup/dictionary-definition-lexic (identifier &optional arg) "Look up the definition of the word at point (or selection) using `lexic-search'." :override #'+lookup/dictionary-definition (interactive (list (or (doom-thing-at-point-or-region 'word) (read-string "Look up in dictionary: ")) current-prefix-arg)) (lexic-search identifier nil nil t)) #+end_src * Orgmode #+begin_src emacs-lisp (after! org (setcdr (assoc "j" org-capture-templates) '("Journal" entry (file+olp+datetree +org-capture-journal-file) "* %(format-time-string \"%H:%M\") %?\n%a\n%i" :clock-in t :clock-resume t)) (add-to-list 'org-capture-templates `("e" "Event" entry (file ,(expand-file-name "caldav.org" org-directory)) "* %?\n%^T\n%i\n%a")) (add-to-list 'org-capture-templates `("i" "Isar-Speak Contact" entry (file ,(expand-file-name "Isar-Speak.org" org-directory)) "* INTRS [[notmuch-search:%:fromaddress][%:fromname]] :PROPERTIES: :EMAIL: %:fromaddress :END: Invited: %^t ")) (setq org-roam-capture-templates '(("d" "default" plain "%i\n%?" :target (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}") :unnarrowed t)) org-roam-capture-ref-templates org-roam-capture-templates)) #+end_src ** Alerts This is to set the reminders of calendar events. Using appt is quite fine. I get a remainder just above the minibuffer There is no loud sound or anything disturbing, just the appearance of this new window. #+BEGIN_SRC emacs-lisp (after! org-agenda (setq appt-display-mode-line t ;; show in the modeline appt-display-format 'echo) ;; use our func (run-at-time "5 minutes" (* 3600 2) 'org-agenda-to-appt) (appt-activate 1) ;; active appt (appointment notification) (display-time) ;; time display is required for this... ;; update appt each time agenda opened (add-hook 'org-agenda-finalize-hook 'org-agenda-to-appt)) #+END_SRC ** Calendar sync #+begin_src emacs-lisp (use-package! cal-sync :load-path "~/dev/org-caldav" :commands (cal-sync-push cal-sync-import-file cal-sync-delete) :init (map! :leader (:prefix-map "mc" "p" #'cal-sync-push "f" #'cal-sync-import-file)) :config (setq cal-sync-url "https://cloud.oscarnajera.com/remote.php/dav/calendars/oscar" cal-sync-calendar-id "personal-1" org-icalendar-date-time-format ":%Y%m%dT%H%M%SZ")) #+end_src ** References #+begin_src emacs-lisp :tangle "packages.el" (package! helm-bibtex) (package! org-ref) #+end_src #+begin_src emacs-lisp (use-package! helm-bibtex :commands helm-bibtex :after org :init (setq bibtex-completion-bibliography (expand-file-name "biblio.bib" org-directory) bibtex-completion-pdf-field "file" bibtex-completion-library-path (expand-file-name "bibtex-pdf/" org-directory) bibtex-completion-notes-path (expand-file-name "roam/" org-directory) bibtex-completion-notes-template-multiple-files "#+TITLE: ${title} (${year})\n#+author: ${author-or-editor}\n") :config (defun bibtex-completion-open-notes-and-pdf (keys) (bibtex-completion-open-pdf keys) (bibtex-completion-edit-notes keys)) (helm-bibtex-helmify-action bibtex-completion-open-notes-and-pdf helm-bibtex-open-notes-and-pdf) ;(helm-delete-action-from-source "Edit notes with PDF" helm-source-bibtex) (helm-add-action-to-source "Edit notes with PDF" 'helm-bibtex-open-notes-and-pdf helm-source-bibtex 1)) (use-package! org-ref :after helm-bibtex) #+end_src ** Letters #+BEGIN_SRC emacs-lisp (use-package ox-latex :ensure org :after org :config ;; APS journals (add-to-list 'org-latex-classes '("revtex4-1" "\\documentclass{revtex4-1} [PACKAGES] [EXTRA]" ("\\section{%s}" . "\\section*{%s}") ("\\subsection{%s}" . "\\subsection*{%s}") ("\\subsubsection{%s}" . "\\subsubsection*{%s}") ("\\paragraph{%s}" . "\\paragraph*{%s}") ("\\subparagraph{%s}" . "\\subparagraph*{%s}"))) (eval-after-load 'ox '(require 'ox-koma-letter)) (add-to-list 'org-latex-packages-alist '("AUTO" "babel" nil)) ) #+END_SRC ** Feeds #+begin_src emacs-lisp (after! elfeed (set-evil-initial-state! 'elfeed-search-mode 'emacs) (set-evil-initial-state! 'elfeed-show-mode 'emacs) (setq elfeed-feeds '("https://sachachua.com/blog/feed" "http://www.howardism.org/index.xml" "https://guix.gnu.org/feeds/blog.atom" "https://ag91.github.io/rss.xml" "https://daryl.wakatara.com/rss.xml" "https://nullprogram.com/feed/" "https://stevelosh.com/rss.xml"))) #+end_src * Email ** Notmuch #+begin_src emacs-lisp :tangle "packages.el" (package! notmuch :pin "7b5921877e748338359a25dae578771f768183af") (package! org-mime :pin "a7bf07316f93015e4f853ea0fc5b8d05b4a7695d") (package! ol-notmuch :pin "126fb446d8fa9e54cf21103afaf506fd81273c02") #+end_src #+BEGIN_SRC emacs-lisp (use-package! notmuch :init (after! org (add-to-list 'org-modules 'ol-notmuch)) (map! :leader (:prefix-map ("o" . "open") :desc "notmuch" "m" #'notmuch)) :commands notmuch :bind (:map notmuch-hello-mode-map ("l" . notmuch-jump-search) ("/" . notmuch-tree) :map notmuch-search-mode-map ("f" . notmuch-search-filter-by-tag) ("/" . notmuch-tree) ("d" . notmuch-search-delete-thread) ("D" . notmuch-search-delete-all) :map notmuch-show-mode-map ("d" . notmuch-show-delete-message) ("D" . notmuch-show-delete-thread-then-exit) ("i" . notmuch-show-tag-spam) ("cb" . on/notmuch-spam-test) ("cr" . org-store-link) ) :config (set-company-backend! 'notmuch-message-mode 'notmuch-company '(company-ispell company-yasnippet)) (setq-default notmuch-search-oldest-first nil) (setq message-directory "~/.mail/" message-auto-save-directory "/tmp/" org-email-link-description-format "%c: %s") (setq notmuch-saved-searches '((:name "inbox" :query "tag:inbox" :key "i" :sort-order newest-first) (:name "Isar-Speak" :query "(tag:Isar-Speak or tag:lists/isar-speak-officers) and tag:unread" :key "t") (:name "flagged" :query "tag:flagged" :key "f") (:name "sent" :query "tag:sent" :key "s") (:name "unread" :query "tag:unread" :key "u") (:name "drafts" :query "tag:draft" :key "d"))) (setq notmuch-show-all-tags-list t notmuch-hello-tag-list-make-query "tag:unread and not tag:killed") (setq notmuch-fcc-dirs '((".*@oscarnajera.com" . "hi_pers/Sent") ;;(".*@gmail.com" . "\"gmail/[Gmail]/.Sent Mail\"") )) (setq notmuch-crypto-process-mime t) (setq message-kill-buffer-on-exit t) (setq notmuch-archive-tags '("-inbox" "-unread")) (setq notmuch-search-line-faces `(("deleted" . (:strike-through "red")) ("flagged" . notmuch-search-flagged-face) ("unread" . notmuch-search-unread-face))) (add-hook! 'doom-real-buffer-functions (defun notmuch-interesting-buffer (b) "Whether the current buffer's major-mode is a notmuch mode." (with-current-buffer b (memq major-mode '(notmuch-show-mode notmuch-search-mode notmuch-tree-mode notmuch-hello-mode notmuch-message-mode))))) (defun notmuch-toggle-tag (tag tags-present) (concat (if (member tag tags-present) "-" "+") tag)) (defun notmuch-show-delete-message () "Delete current message if already marked as deleted undo." (interactive) (notmuch-show-tag-message (notmuch-toggle-tag "deleted" (notmuch-show-get-tags)))) (defun on/bogofilter (&rest args) "Call bogofilter on current notmuch-show-file with ARGS." (let ((msg-file (notmuch-show-get-filename))) (with-temp-buffer (apply #'call-process "bogofilter" msg-file t nil args) (message (string-trim (buffer-string)))))) (defun on/notmuch-spam-test () "Evaluate spaminess of message." (interactive) (on/bogofilter "-v")) (defun on/bogofilter-set-spam (spam-p) "Set spam or ham depending according to SPAM-P." (on/bogofilter "-v" (if spam-p "-s" "-n"))) (defun notmuch-show-tag-spam () "Tag spam on current message if already marked as spam undo." (interactive) (let ((tag (notmuch-toggle-tag "spam" (notmuch-show-get-tags)))) (notmuch-show-tag-message tag) (on/bogofilter-set-spam (string-prefix-p "+" tag)))) (defun notmuch-show-delete-thread-then-exit () "Delete all messages in the current buffer, then exit back to search results." (interactive) (notmuch-show-tag-all '("+deleted")) (notmuch-show-next-thread)) (defun notmuch-search-delete-thread() "Delete all messages in the current thread or undelete" (interactive) (notmuch-search-tag (list (notmuch-toggle-tag "deleted" (notmuch-search-get-tags))))) (defun notmuch-search-delete-all() "Delete all messages in the current buffer" (interactive) (notmuch-search-tag-all '("+deleted" "-inbox" "-unread"))) (define-key notmuch-tree-mode-map "d" (lambda () "delete message" (interactive) (notmuch-tree-tag (list (notmuch-toggle-tag "deleted" (notmuch-tree-get-tags))))))) (use-package! org-mime :after (org notmuch) :config (setq org-mime-library 'mml)) (require 'comint) (require 'ansi-color) (defun on/fetch-all-email () "Start tagmail fetch on a subprocess." (interactive) (with-current-buffer (get-buffer-create "*E-mail fetch*") (pop-to-buffer (current-buffer)) (comint-mode) (ansi-color-for-comint-mode-on) (make-process :name "E-mail fetch" :buffer (current-buffer) :command '("tagmail") :filter #'comint-output-filter))) #+END_SRC ** Sending email #+begin_src emacs-lisp (after! notmuch (setq send-mail-function 'smtpmail-send-it message-send-mail-function 'message-smtpmail-send-it smtpmail-local-domain "oscarnajera.com") (defun set-smtp-server () (let* ((default-smtp-conf '("mail.oscarnajera.com" 587 starttls "hi")) (smtp-from-server-alist '(("Oscar Najera " "smtp.googlemail.com" 587 starttls "najera.oscar"))) (smtp-conf (alist-get (save-restriction (message-narrow-to-headers) (message-fetch-field "from")) smtp-from-server-alist default-smtp-conf nil #'string=))) (-let [(server port protocol user) smtp-conf] (setq smtpmail-smtp-server server smtpmail-smtp-service port smtpmail-stream-type protocol smtpmail-smtp-user user) (message "SMTP server changed to %s in port %s by %s" server port protocol)))) (add-hook 'message-send-mail-hook 'set-smtp-server)) #+end_src * Ledger Emacs mode for managing ledger text files #+BEGIN_SRC emacs-lisp (after! ledger-mode (setq ledger-default-date-format ledger-iso-date-format) (defun on/ledger-link-invoice () "Attach an invoice file to this posting." (interactive) (when-let* ((date (ledger-xact-date)) (payee (replace-regexp-in-string " " "_" (string-trim-right (ledger-xact-payee)))) (src-file (read-file-name "Attach: " "~/dev/journal/Empresa_DE/")) (file-name (concat "Empresa_DE/" date "_" payee "." (file-name-extension src-file)))) (ledger-navigate-beginning-of-xact) (end-of-line) (rename-file src-file (expand-file-name file-name "/home/titan/dev/journal/")) (newline) (insert " ; Invoice: " file-name)))) #+end_src ** CSV #+begin_src emacs-lisp :tangle "packages.el" (package! parse-csv) (package! emacsql-sqlite3) #+end_src ** Crypto #+begin_src emacs-lisp (use-package! cardano-tx :commands (cardano-tx-new cardano-tx-cli-tip) :load-path "~/dev/cardano/emacs-wallet" :init (defun on/cardano-set-network () (interactive) (let* ((networks '((:mainnet "/tmp/alinamn.socket" "http://localhost:8090" "--mainnet") (:testnet "/tmp/alinatn.socket" "http://localhost:8091" "--testnet-magic" "1097911063") (:vasil "/home/titan/test-cardano/dev-vasil/bp-vasil.socket" "http://localhost:8093" "--testnet-magic" "9") )) (pick (alist-get (completing-read "Pick network" networks) networks nil nil #'string=))) (setq cardano-tx-cli-node-socket (expand-file-name (car pick)) cardano-wallet-url (cadr pick) cardano-tx-cli-network-args (cddr pick)))) :config (add-hook! 'doom-real-buffer-functions (defun cardano-interesting-buffer (b) "Whether the current buffer's major-mode is a cardano mode." (with-current-buffer b (memq major-mode '(cardano-db-addresses-mode cardano-db-files-mode cardano-tx-mode cardano-wallet-tx-log-mode))))) (setq cardano-tx-log-level 'debug) ;; (setq cardano-cli-command (expand-file-name "~/dev/cardano/cardano-node/cli")) (setq cardano-tx-cli-command "/home/titan/dev/cardano/cardano-node/dist-newstyle/build/x86_64-linux/ghc-8.10.7/cardano-cli-1.35.0/x/cardano-cli/build/cardano-cli/cardano-cli") (setq cardano-tx-db-keyring-dir "~/dev/cardano/emacs-wallet/keys/demo")) (use-package! cardano-wallet :commands (cardano-wallet-balances) :load-path "~/dev/cardano/emacs-wallet") #+end_src #+RESULTS: * Books #+begin_src emacs-lisp :tangle "packages.el" (package! nov) (package! calibredb) #+end_src #+begin_src emacs-lisp (use-package! nov :mode (("\\.epub\\'" . nov-mode))) (use-package! calibredb :commands calibredb :config (set-evil-initial-state! 'calibredb-search-mode 'emacs) (setq calibredb-root-dir "/run/media/titan/ext_backup/personal/Libros/CalibreManaged") (setq calibredb-db-dir (expand-file-name "metadata.db" calibredb-root-dir))) #+end_src * Programming languages ** YAML #+begin_src emacs-lisp :tangle "packages.el" (package! yaml) #+end_src #+begin_src emacs-lisp (use-package! libyaml :commands yaml-read-file :load-path "~/dev/emacs-lisp/emacs-libyaml/") (use-package! yaml) #+end_src ** Databases #+begin_src emacs-lisp :tangle "packages.el" (package! emacsql-psql) #+end_src ** WEB #+begin_src emacs-lisp (after! web-mode (setq-hook! 'web-mode-hook +format-with :none)) #+end_src ** Haskell #+begin_src emacs-lisp (after! haskell-mode (setq-hook! 'haskell-mode-hook +format-with :none) (setq haskell-stylish-on-save t lsp-haskell-formatting-provider "stylish-haskell")) #+end_src * Admin #+begin_src emacs-lisp :tangle "packages.el" (package! guix) #+end_src #+begin_src emacs-lisp (use-package! guix) #+end_src #+begin_src emacs-lisp :tangle "packages.el" (package! json-rpc) #+end_src #+begin_src emacs-lisp (use-package! json-rpc) #+end_src #+begin_src emacs-lisp (use-package! shepherd :load-path "~/dev/dotfiles/elisp/" :commands (shepherd)) #+end_src