Skip to content

cedricchevalier19/dotemacs

Repository files navigation

My Emacs configuration

My Emacs configuration

It is inspired by:

Preconfiguration

Header

lexical-binding is Necessary for some lambdas used to configure org-roam.

;; -*- lexical-binding: t -*-
;;; My emacs configuration
;;; Commentary:
;;; Generated from readme.org
;;; Do not editorial

;;; Code:

Package management

(require 'package)
(add-to-list 'package-archives '("gnu"   . "https://elpa.gnu.org/packages/"))
(add-to-list 'package-archives '("melpa" . "https://melpa.org/packages/"))
(package-initialize)

(unless (package-installed-p 'use-package)
  (package-refresh-contents)
  (package-install 'use-package))
(eval-and-compile
  (require 'use-package)
  (setq use-package-always-ensure t
        use-package-expand-minimally t))
(use-package bind-key)

Customization

Follow PARA method with org-roam:

  • Project: Short-term efforts
  • Area: Long-term responsibilities
  • Resource: interests
  • Archive: Inactive items
(defconst org-directory "~/org/"
  "org-mode directory, where most of the org-mode file lives")
(defconst org-roam-directory (expand-file-name "roam" org-directory)
  "Org-roam base directory")

(defconst org-projects-dir (expand-file-name "projects" org-roam-directory)
  "Primary tasks directory.")
(defconst org-inbox-file (expand-file-name "inbox.org" org-projects-dir)
  "New stuff collected in this file.")
(defconst org-icalendar-file (expand-file-name "calendar.org" org-roam-directory)
  "Synchronize with office calendar")
(defconst org-people-file (expand-file-name "people.org" org-roam-directory)
  "org-contacts for colleagues")

(defconst org-home-dir (expand-file-name "home" org-roam-directory)
  "Home/personal roam directory")
(defconst org-friends-file (expand-file-name "friends.org" org-home-dir)
  "org-contacts for friends")

(defconst org-area-dir (expand-file-name "area" org-roam-directory)
  "Primary Area directory.")

(defconst org-references-dir (expand-file-name "references" org-roam-directory)
  "Primary Area directory.")
(defconst org-roam-bibfile (expand-file-name "zotero.bib" org-references-dir)
  "Main bibfile")

(defconst org-archive-dir (expand-file-name "archive" org-roam-directory)
  "Directory of shareable, technical notes.")
(defconst org-completed-dir (expand-file-name "projects" org-archive-dir)
  "Directory of completed project files.")

Generic

(use-package no-littering
  :demand t
  :commands (no-littering-expand-etc-file-name)
  :init
  (require 'recentf)

  (setq no-littering-etc-directory (expand-file-name "etc" user-emacs-directory))
  (setq no-littering-var-directory (expand-file-name "var" user-emacs-directory))
  ;; exclude from recentf
  (add-to-list 'recentf-exclude no-littering-var-directory)
  (add-to-list 'recentf-exclude no-littering-etc-directory)
  ;; store auto save files in the var directory.
  :config
  (setq auto-save-file-name-transforms
        `((".*" ,(no-littering-expand-var-file-name "auto-save/") t))))

(customize-set-variable 'load-prefer-newer t) ;; load newer bytecode
;;;; auto compile
(use-package auto-compile
  :demand t
  :init
  (auto-compile-on-load-mode))

(use-package diminish
  :defer t)
(setq-default
 auto-save-list-file-name  (expand-file-name "local/auto-save-list"
                                             user-emacs-directory)
 custom-file  (expand-file-name "local/custom.el"
                                user-emacs-directory))
(when (file-exists-p custom-file)
  (load custom-file t))

Programming

Formatting

(use-package apheleia
  :config
  (apheleia-global-mode +1))
(use-package clang-format)

Documentation

(use-package devdocs
  :bind (("C-h D" . devdocs-lookup))
  :hook
  (cmake-mode . (lambda () (setq-local devdocs-current-docs '("cmake~3.24"))))
  (sh-mode . (lambda () (setq-local devdocs-current-docs '("bash"))))
  )

Dumb-jump

https://github.com/jacktasia/dumb-jump

(use-package dumb-jump
  :custom
  (dump-jump-force-searcher 'rg)
  (xref-show-definitions-function #'xref-show-definitions-completing-read)
  :config
  (add-hook 'xref-backend-functions #'dumb-jump-xref-activate)
  )

CMake

Edit

(use-package cmake-mode
  :mode ("CMakeLists.txt'" "\\.cmake\\'"))

(use-package cmake-font-lock
  :after (cmake-mode)
  :hook (cmake-mode . cmake-font-lock-activate))

Develop

Meson

(use-package meson-mode
  :mode ("meson.build'" "meson_options.txt'"))

Git

Magit

(use-package magit
  :bind (("C-x g" . magit-status)))

Current modifications

(use-package diff-hl
  :after vc
  :config
  (setq diff-hl-draw-borders nil)
  (setq diff-hl-side 'left)
  :hook (after-init-hook . global-diff-hl-mode))

gitlab support

Forge

(use-package forge
  :after magit
  ;;  :config (setq auth-sources '("~/.authinfo"))
  )

From https://magit.vc/manual/ghub/Storing-a-Token.html#Storing-a-Token

git config --global github.user USERNAME

The variable auth-sources controls how and where Auth-Source keeps its secrets. The default value is a list of three files: (“~/.authinfo” “~/.authinfo.gpg” “~/.netrc”), but to avoid confusion you should make sure that only one of these files exists and then you should also adjust the value of the variable to only ever use that file, for example:

(setq auth-sources ‘(“~/.authinfo”))

In ~/.authinfo secrets are stored in plain text. If you don’t want that, then you should use the encrypted ~/.authinfo.gpg instead:

(setq auth-sources ‘(“~/.authinfo.gpg”))

Auth-Source also supports storing secrets in various external key-chains. See (auth)Top for more information.

The default Auth-Source backends only support storing three values per entry; the “machine”, the “login” and the “password”. Because Ghub uses separate tokens for each package, it has to squeeze four values into those three slots, and it does that by using “USERNAME^PACKAGE” as the “login”.

Assuming your Github username is “ziggy”, the package is named “forge”, and you want to access Github.com, an entry in one of the three mentioned files would then look like this:

machine api.github.com login ziggy^forge password 012345abcdef…

Assuming your Gitlab username is “ziggy”, the package is named “forge”, and you want to access Gitlab.com, an entry in one of the three mentioned files would then look like this:

machine gitlab.com/api/v4 login ziggy^forge password 012345abcdef..

Python

(use-package python-black
  :demand t
  :after python
  :hook (python-mode . python-black-on-save-mode))

Yaml

(use-package yaml-mode
  :init (setq yapfify-executable "yapf3")
  :mode ("\\.yml\\'" . yaml-mode))

Docker

(use-package docker
  :bind ("C-c d" . docker))

(use-package dockerfile-mode
  :mode ("Dockerfile\\'" "\\.dockerfile$"))

Markdown

Needs pandoc

(use-package markdown-mode
  :delight "μ "
  :mode ("\\.markdown\\'" "\\.md\\'")
  :custom (markdown-command "/usr/bin/pandoc"))

RST

plain

(use-package rst
  :delight "rst"
  :mode (("\\.rst$" . rst-mode)
         ("\\.rest$" . rst-mode)))

sphinx

(use-package sphinx-mode
  :after rst)

Shell scripts

Exec rights

The snippet below ensures that the execution right is automatically granted to save a shell script file that begins with a #! shebang:

(use-package sh-script
  :ensure nil
  :hook (after-save . executable-make-buffer-file-executable-if-script-p))

Fish support

(use-package fish-mode
  :mode ("\\.fish\\'"))

Rust

rust-analyser must be installed before (https://rust-analyzer.github.io/manual.html#installation)

rustup component add rust-analyzer

From https://www.bytedude.com/setting-up-rust-support-in-emacs/

(use-package rustic
  :defer t
  :config
  (setq
   ;; eglot seems to be the best option right now.
   rustic-lsp-client 'eglot
   rustic-format-on-save nil
   ;; Prevent automatic syntax checking, which was causing lags and stutters.
   eglot-send-changes-idle-time (* 60 60)
   rustic-analyzer-command '("~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/bin/rust-analyzer")
   )
  ;; Disable the annoying doc popups in the minibuffer.
  (add-hook 'eglot-managed-mode-hook (lambda () (eldoc-mode -1)))
  ;;:mode ("\\.rs\\'" "Cargo.toml\\'")
  )

Parentheses

(use-package smartparens
  :diminish smartparens-mode
  :config
  (smartparens-global-mode)
  ;; (sp-local-pair 'org-mode "*" "*")
  ;; (sp-local-pair 'org-mode "_" "_")
  )

(use-package highlight-parentheses
  :diminish highlight-parentheses-mode
  :config (global-highlight-parentheses-mode))

(defvar show-paren-delay 0)
(show-paren-mode t)

Pantuml

(use-package plantuml-mode
  :config
  (setq org-plantuml-jar-path
        (expand-file-name "/usr/share/plantuml/plantuml.jar"))
  (setq plantuml-default-exec-mode 'jar)
  :mode ("\\.plantuml\\'"))

Project

(use-package project)

Interface

Theme

(use-package twilight-bright-theme
  :config
  (load-theme 'twilight-bright t))

Better display for text

(use-package olivetti
  :diminish
  :config
  (setq olivetti-body-width 0.7)
  (setq olivetti-minimum-body-width 80)
  (setq olivetti-recall-visual-line-mode-entry-state t))

Which-key

(use-package which-key
  :commands which-key-mode)

Regular expressions

(use-package visual-regexp-steroids
  :commands vr/replace)

Casual

(use-package casual-dired
  :after dired
  :bind (:map dired-mode-map
              ("C-o" . #'casual-dired-tmenu)
              ("s" . #'casual-dired-sort-by-tmenu)))

Multiple-cursors

(use-package multiple-cursors
  :bind (("C-C m c" . mc/edit-lines)))

Dimmer

https://github.com/gonewest818/dimmer.el

(use-package dimmer
  :custom
  (dimmer-adjustment-mode :background)
  (dimmer-fraction 0.1)
  (dimmer-configure-company-box)
  (dimmer-configure-which-key)
  (dimmer-configure-magit)
  :config
  (dimmer-mode))

Note: dimmer-adjustment-mode is set to :background to avoid a Wrong type argument: stringp, reset with emacs 29, see gonewest818/dimmer.el#69

Dired

(use-package dired
  :ensure nil
  :config
  (when (string= system-type "darwin")
    (setq dired-use-ls-dired nil)))

Dashboard

(use-package all-the-icons
  :if (display-graphic-p))

(use-package dashboard
  :after all-the-icons
  :init
  (dashboard-setup-startup-hook)
  :config
  ;; Dashboard requirements.
  (use-package page-break-lines)
  (use-package all-the-icons)
  ;; Dashboard configuration.
  (setq dashboard-banner-logo-title "Welcome to Emacs")
  (setq dashboard-startup-banner 'logo)
  (setq dashboard-items '((recents   . 5)
                          (agenda    . 5)))
  (setq dashboard-set-init-info t)
  (setq dashboard-set-heading-icons t)
  (setq dashboard-set-file-icons t)

  ;; adds a clock
  (defun dashboard-insert-custom (list-size)
    (defun string-centralized (str)
      (let* ((indent
              (concat "%"
                      (number-to-string
                       (/ (- (window-body-width) (string-width str)) 2))
                      "s"))
             (str (concat indent str indent)))
        (format str " " " ")))

    (insert (propertize (string-centralized (format-time-string "%a %d %b %Y" (current-time))) 'font-lock-face '('bold :foreground "#6c4c7b")))
    (newline)
    (insert (propertize (string-centralized (format-time-string "%H:%M" (current-time))) 'font-lock-face '('bold :foreground "#6c4c7b"))))

  (add-to-list 'dashboard-item-generators  '(custom . dashboard-insert-custom))
  (add-to-list 'dashboard-items '(custom) t)

  (defun test-dashboard () (setq *my-timer* (run-at-time "20 sec" nil #'(lambda ()
                                                                          (when *my-timer*
                                                                            (cancel-timer *my-timer*)
                                                                            (setq *my-timer* nil))
                                                                          (when (string=
                                                                                 (buffer-name (window-buffer))
                                                                                 "*dashboard*")
                                                                            (dashboard-refresh-buffer))))))
  (add-hook 'dashboard-mode-hook #'test-dashboard))

Features

Consult

https://github.com/minad/consult

;; Example configuration for Consult
(use-package consult
  ;; Replace bindings. Lazily loaded due by `use-package'.
  :bind (;; C-c bindings (mode-specific-map)
         ("C-c h" . consult-history)
         ("C-c m" . consult-mode-command)
         ("C-c k" . consult-kmacro)
         ;; C-x bindings (ctl-x-map)
         ("C-x M-:" . consult-complex-command)     ;; orig. repeat-complex-command
         ("C-x b" . consult-buffer)                ;; orig. switch-to-buffer
         ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
         ("C-x 5 b" . consult-buffer-other-frame)  ;; orig. switch-to-buffer-other-frame
         ("C-x r b" . consult-bookmark)            ;; orig. bookmark-jump
         ("C-x p b" . consult-project-buffer)      ;; orig. project-switch-to-buffer
         ;; Custom M-# bindings for fast register access
         ("M-#" . consult-register-load)
         ("M-'" . consult-register-store)          ;; orig. abbrev-prefix-mark (unrelated)
         ("C-M-#" . consult-register)
         ;; Other custom bindings
         ("M-y" . consult-yank-pop)                ;; orig. yank-pop
         ("<help> a" . consult-apropos)            ;; orig. apropos-command
         ;; M-g bindings (goto-map)
         ("M-g e" . consult-compile-error)
         ("M-g f" . consult-flymake)               ;; Alternative: consult-flycheck
         ("M-g g" . consult-goto-line)             ;; orig. goto-line
         ("M-g M-g" . consult-goto-line)           ;; orig. goto-line
         ("M-g o" . consult-outline)               ;; Alternative: consult-org-heading
         ("M-g m" . consult-mark)
         ("M-g k" . consult-global-mark)
         ("M-g i" . consult-imenu)
         ("M-g I" . consult-imenu-multi)
         ;; M-s bindings (search-map)
         ("M-s d" . consult-find)
         ("M-s D" . consult-locate)
         ("M-s g" . consult-grep)
         ("M-s G" . consult-git-grep)
         ("M-s r" . consult-ripgrep)
         ("M-s l" . consult-line)
         ("M-s L" . consult-line-multi)
         ("M-s m" . consult-multi-occur)
         ("M-s k" . consult-keep-lines)
         ("M-s u" . consult-focus-lines)
         ;; Isearch integration
         ("M-s e" . consult-isearch-history)
         :map isearch-mode-map
         ("M-e" . consult-isearch-history)         ;; orig. isearch-edit-string
         ("M-s e" . consult-isearch-history)       ;; orig. isearch-edit-string
         ("M-s l" . consult-line)                  ;; needed by consult-line to detect isearch
         ("M-s L" . consult-line-multi)            ;; needed by consult-line to detect isearch
         ;; Minibuffer history
         :map minibuffer-local-map
         ("M-s" . consult-history)                 ;; orig. next-matching-history-element
         ("M-r" . consult-history))                ;; orig. previous-matching-history-element

  ;; Enable automatic preview at point in the *Completions* buffer. This is
  ;; relevant when you use the default completion UI.
  :hook (completion-list-mode . consult-preview-at-point-mode)

  ;; The :init configuration is always executed (Not lazy)
  :init

  ;; Optionally configure the register formatting. This improves the register
  ;; preview for `consult-register', `consult-register-load',
  ;; `consult-register-store' and the Emacs built-ins.
  (setq register-preview-delay 0.5
        register-preview-function #'consult-register-format)

  ;; Optionally tweak the register preview window.
  ;; This adds thin lines, sorting and hides the mode line of the window.
  (advice-add #'register-preview :override #'consult-register-window)

  ;; Use Consult to select xref locations with preview
  (setq xref-show-xrefs-function #'consult-xref
        xref-show-definitions-function #'consult-xref)

  ;; Configure other variables and modes in the :config section,
  ;; after lazily loading the package.
  :config

  ;; Optionally configure preview. The default value
  ;; is 'any, such that any key triggers the preview.
  ;; (setq consult-preview-key 'any)
  ;; (setq consult-preview-key (kbd "M-."))
  ;; (setq consult-preview-key (list (kbd "<S-down>") (kbd "<S-up>")))
  ;; For some commands and buffer sources it is useful to configure the
  ;; :preview-key on a per-command basis using the `consult-customize' macro.
  (consult-customize
   consult-theme :preview-key '(:debounce 0.2 any)
   consult-ripgrep consult-git-grep consult-grep
   consult-bookmark consult-recent-file consult-xref
   consult--source-bookmark consult--source-file-register
   consult--source-recent-file consult--source-project-recent-file
   ;; :preview-key (kbd "M-.")
   :preview-key '(:debounce 0.4 any))

  ;; Optionally configure the narrowing key.
  ;; Both < and C-+ work reasonably well.
  (setq consult-narrow-key "<") ;; (kbd "C-+")

  ;; Optionally make narrowing help available in the minibuffer.
  ;; You may want to use `embark-prefix-help-command' or which-key instead.
  ;; (define-key consult-narrow-map (vconcat consult-narrow-key "?") #'consult-narrow-help)

  ;; By default `consult-project-function' uses `project-root' from project.el.
  ;; Optionally configure a different project root function.
  ;; There are multiple reasonable alternatives to chose from.
  ;;;; 1. project.el (the default)
  ;; (setq consult-project-function #'consult--default-project--function)
  ;;;; 2. projectile.el (projectile-project-root)
  ;; (autoload 'projectile-project-root "projectile")
  ;; (setq consult-project-function (lambda (_) (projectile-project-root)))
  ;;;; 3. vc.el (vc-root-dir)
  ;; (setq consult-project-function (lambda (_) (vc-root-dir)))
  ;;;; 4. locate-dominating-file
  ;; (setq consult-project-function (lambda (_) (locate-dominating-file "." ".git")))
  )

(use-package consult-dir
  :bind (("C-x C-d" . consult-dir)
         :map minibuffer-local-completion-map
         ("C-x C-d" . consult-dir)
         ("C-x C-j" . consult-dir-jump-file)
         :map selectrum-minibuffer-map
         ("C-x C-d" . consult-dir)
         ("C-x C-j" . consult-dir-jump-file)))

(use-package consult-eglot)

(use-package consult-org-roam
  :after org-roam
  :defer t
  :init
  (require 'consult-org-roam)
  ;; Activate the minor mode
  (consult-org-roam-mode 1)
  :custom
  ;; Use `ripgrep' for searching with `consult-org-roam-search'
  (consult-org-roam-grep-func #'consult-ripgrep)
  ;; Configure a custom narrow key for `consult-buffer'
  (consult-org-roam-buffer-narrow-key ?r)
  ;; Display org-roam buffers right after non-org-roam buffers
  ;; in consult-buffer (and not down at the bottom)
  (consult-org-roam-buffer-after-buffers t)
  :config
  ;; Eventually suppress previewing for certain functions
  (consult-customize
   consult-org-roam-forward-links
   :preview-key (kbd "M-."))
  :bind
  ;; Define some convenient keybindings as an addition
  ("C-c n e" . consult-org-roam-file-find)
  ("C-c n b" . consult-org-roam-backlinks)
  ("C-c n l" . consult-org-roam-forward-links)
  ("C-c n r" . consult-org-roam-search))

Marginalia

https://github.com/minad/marginalia

;; Enable rich annotations using the Marginalia package
(use-package marginalia
  ;; Either bind `marginalia-cycle' globally or only in the minibuffer
  :bind (("M-A" . marginalia-cycle)
         :map minibuffer-local-map
         ("M-A" . marginalia-cycle))

  ;; The :init configuration is always executed (Not lazy!)
  :init

  ;; Must be in the :init section of use-package such that the mode gets
  ;; enabled right away. Note that this forces loading the package.
  (marginalia-mode))

(use-package embark

  :bind
  (("C-." . embark-act)         ;; pick some comfortable binding
   ("C-;" . embark-dwim)        ;; good alternative: M-.
   ("C-h B" . embark-bindings)) ;; alternative for `describe-bindings'

  :init

  ;; Optionally replace the key help with a completing-read interface
  (setq prefix-help-command #'embark-prefix-help-command)

  :config

  ;; Hide the mode line of the Embark live/completions buffers
  (add-to-list 'display-buffer-alist
               '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
                 nil
                 (window-parameters (mode-line-format . none)))))

;; Consult users will also want the embark-consult package.
(use-package embark-consult
  :hook
  (embark-collect-mode . consult-preview-at-point-mode))

Vertigo

;; Enable vertico
(use-package vertico
  :init
  (vertico-mode)

  ;; Different scroll margin
  ;; (setq vertico-scroll-margin 0)

  ;; Show more candidates
  ;; (setq vertico-count 20)

  ;; Grow and shrink the Vertico minibuffer
  ;; (setq vertico-resize t)

  ;; Optionally enable cycling for `vertico-next' and `vertico-previous'.
  ;; (setq vertico-cycle t)
  )

;; Persist history over Emacs restarts. Vertico sorts by history position.
(use-package savehist
  :init
  (savehist-mode))

;; A few more useful configurations...
(use-package emacs
  :init
  ;; Add prompt indicator to `completing-read-multiple'.
  ;; We display [CRM<separator>], e.g., [CRM,] if the separator is a comma.
  (defun crm-indicator (args)
    (cons (format "[CRM%s] %s"
                  (replace-regexp-in-string
                   "\\`\\[.*?]\\*\\|\\[.*?]\\*\\'" ""
                   crm-separator)
                  (car args))
          (cdr args)))
  (advice-add #'completing-read-multiple :filter-args #'crm-indicator)

  ;; Do not allow the cursor in the minibuffer prompt
  (setq minibuffer-prompt-properties
        '(read-only t cursor-intangible t face minibuffer-prompt))
  (add-hook 'minibuffer-setup-hook #'cursor-intangible-mode)

  ;; Emacs 28: Hide commands in M-x which do not work in the current mode.
  ;; Vertico commands are hidden in normal buffers.
  ;; (setq read-extended-command-predicate
  ;;       #'command-completion-default-include-p)

  ;; Enable recursive minibuffers
  (setq enable-recursive-minibuffers t))

;; Optionally use the `orderless' completion style.
(use-package orderless
  :init
  ;; Configure a custom style dispatcher (see the Consult wiki)
  ;; (setq orderless-style-dispatchers '(+orderless-dispatch)
  ;;       orderless-component-separator #'orderless-escapable-split-on-space)
  (setq completion-styles '(orderless flex)
        completion-category-defaults nil
        completion-category-overrides '((file (styles partial-completion)) (eglot (styles . (orderless flex))))))

Completion

corfu is used

(use-package corfu
  ;; Optional customizations
  :custom
  (corfu-cycle t)                ;; Enable cycling for `corfu-next/previous'
  (corfu-auto t)                 ;; Enable auto completion
  ;; (corfu-separator ?\s)          ;; Orderless field separator
  ;; (corfu-quit-at-boundary nil)   ;; Never quit at completion boundary
  ;; (corfu-quit-no-match nil)      ;; Never quit, even if there is no match
  ;; (corfu-preview-current nil)    ;; Disable current candidate preview
  ;; (corfu-preselect-first nil)    ;; Disable candidate preselection
  ;; (corfu-on-exact-match nil)     ;; Configure handling of exact matches
  ;; (corfu-scroll-margin 5)        ;; Use scroll margin

  ;; Enable Corfu only for certain modes.
  ;; :hook ((prog-mode . corfu-mode)
  ;;        (shell-mode . corfu-mode)
  ;;        (eshell-mode . corfu-mode))

  :bind (:map corfu-map
              ("C-j" . corfu-next)
              ("C-k" . corfu-previous)
              ("TAB" . corfu-insert)
              ("RET" . nil))

  ;; Recommended: Enable Corfu globally.
  ;; This is recommended since Dabbrev can be used globally (M-/).
  ;; See also `corfu-excluded-modes'.
  :init
  (global-corfu-mode)
  (global-set-key (kbd "M-i") #'completion-at-point)
  )

Indent

Indent

(use-package indent-tools
  :bind (("C-C >" .'indent-tools-hydra/body)))

editor config

(use-package editorconfig
  :defer 0.3
  :config (editorconfig-mode 1))

eglot

Core

(use-package eglot
  :init
  (setq exec-path (append '("~/opt/lsp-tools/bin") exec-path))
  ;; Option 1: Specify explicitly to use Orderless for Eglot
  (setq completion-category-overrides '((eglot (styles orderless))))
  :config
  (add-hook 'c-mode-hook 'eglot-ensure)
  (add-hook 'c++-mode-hook 'eglot-ensure)
  (setq completion-category-defaults nil)
  )

debugger

;; (use-package dap-mode
;;   :disabled)
;; (use-package dap-LANGUAGE) to load the dap adapter for your language

Flycheck

(use-package flycheck
  :init (global-flycheck-mode))

Jinx

https://github.com/minad/jinx

Jinx a just-in-time spell-checker. It requires enchant.

On mac:

brew install enchant
(use-package jinx
  :hook (emacs-startup . global-jinx-mode)
  :custom
  (add-to-list 'vertico-multiform-categories
               '(jinx grid (vertico-grid-annotate . 20)))
  (vertico-multiform-mode 1)
  :bind (("M-$" . jinx-correct)
         ("C-M-$" . jinx-languages)))

Org

Main config

(use-package org
  :mode (("\\.org$" . org-mode)
         ("\\.org.draft$" . org-mode))

  :config
  (setq org-latex-logfiles-extensions
        '("acn" "ind" "ilg" "ist" "glo" "tex" "synctex.gz"))

  :custom
  (require 'org-inlinetask)
            ;;;;;;; Files
  ;; setup archive directory in current folder
            ;;;;;;; Org source
  (org-ctrl-k-protect-subtree 'error)
  (org-startup-indented t)
  (org-catch-invisible-edits 'smart)
            ;;;;;;; Structure and Appearance
  (org-display-remote-inline-images 'cache)
  (org-insert-heading-respect-content t)
  (org-list-allow-alphabetical t)
  (org-hide-emphasis-markers t)
  (org-use-sub-superscripts '{})
  (org-use-speed-commands t)
  (org-yank-folded-subtrees t)
  (org-yank-adjusted-subtrees t)
  (org-blank-before-new-entry
   '((heading . auto)
     (plain-list-item . auto)))

  :bind
  (("C-c a" . org-agenda)
   ("C-c c" . org-capture)
   ("C-c b" . org-switchb)
   ("C-c i" . (lambda () "Open inbox capture window"
                (interactive)
                (org-capture nil "i")))
   ("C-c l" . org-store-link)
   ("C-c r" . org-refile)
   ;; Skeletons
   (:map org-mode-map
         ("C-c C-x h" . org-toggle-link-display)
         ("C-c C-s" . org-schedule))
   )
  )
(with-eval-after-load 'org
  (setq org-use-speed-commands t
        org-special-ctrl-a/e t
        org-special-ctrl-k t
        org-todo-keywords '((sequence "TODO(t)" "NEXT(n)" "INPROGRESS(p)" "|" "DONE(d!)" "CANCELED(c@/!)")
                            (sequence "WAITING(w@/!)" "SOMEDAY(s)" "|" "CANCELED(c@/!)" "MEETING(m)")
                            (sequence "IDEA(i)" "|" "CANCELED(c@/!)"))
        org-todo-state-tags-triggers '(("CANCELLED" ("CANCELLED" . t))
                                       ("WAITING" ("WAITING" . t))
                                       (done ("WAITING"))
                                       ("TODO" ("WAITING") ("CANCELLED"))
                                       ("NEXT" ("WAITING") ("CANCELLED"))
                                       ("DONE" ("WAITING") ("CANCELLED")))
        org-use-tag-inheritance t
        org-tag-alist '(("Research") ("Collab") ("Teaching") ("Codesign")
                        ("Kokkos") ("C++") ("Rust") ("Arcane")
                        ("docs") ("code") ("review")
                        (:startgroup . nil)
                        ("#home" . ?h) ("#work" . ?w)
                        (:endgroup . nil)
                        (:startgroup . nil)
                        ("#link" . ?i) ("#read" . ?r) ("#project" . ?p)
                        (:endgroup . nil))
        org-log-done 'time
        org-log-redeadline 'time
        org-log-reschedule 'time
        org-log-into-drawer t
        org-enforce-todo-dependencies t
        org-refile-allow-creating-parent-nodes 'confirm
        org-columns-default-format "%80ITEM(Task) %TODO %3PRIORITY %10Effort(Effort){:} %10CLOCKSUM"
        org-fontify-whole-heading-line t
        org-pretty-entities t
        org-ellipsis ""
        org-archive-location (concat org-completed-dir "/%s::datetree/")
        org-use-property-inheritance t
        org-priority 67
        org-priority-faces '((?A . "#ff2600")
                             (?B . "#ff5900")
                             (?C . "#ff9200")
                             (?D . "#747474"))
        org-global-properties (quote (("EFFORT_ALL" . "0:15 0:30 0:45 1:00 2:00 3:00 4:00 5:00 6:00 0:00")
                                      ("STYLE_ALL" . "habit")))
        org-blank-before-new-entry '((heading . t)
                                     (plain-list-item . nil)))
  )

Org-agenda

(use-package org-super-agenda
  :after org
  :defer t
  :custom
  (org-agenda-include-diary t)
  (org-agenda-custom-commands
   '(("z" "Zall"
      ((agenda "" ((org-agenda-span 'day)
                   (org-super-agenda-groups
                    '((:name "Today"
                             :time-grid t
                             :date today
                             :todo "TODAY"
                             :scheduled today
                             :order 1)))))
       (alltodo "" ((org-agenda-overriding-header "")
                    (org-super-agenda-groups
                     '((:name "Next to do"
                              :todo "NEXT"
                              :order 1)
                       (:name "Important"
                              :tag "Important"
                              :priority "A"
                              :order 6)
                       (:name "Due Today"
                              :deadline today
                              :order 2)
                       (:name "Due Soon"
                              :deadline future
                              :order 8)
                       (:name "Overdue"
                              :deadline past
                              :order 7)
                       (:name "Projects"
                              :tag "Project"
                              :order 14)
                       (:name "Waiting"
                              :todo "WAITING"
                              :order 20)))))))
     ("g" "Grouped by project"
      ((agenda "" ((org-agenda-span 'week)
		   (org-super-agenda-groups
		    '((:auto-group t)))))))
     ("b" "Best"
      ((agenda "" ((org-agenda-span 'week)
		   (org-super-agenda-groups
		    '((:log t)  ; Automatically named "Log"
		      (:name "Schedule"
			     :time-grid t)
		      (:name "Today"
			     :scheduled today)
		      (:habit t)
		      (:name "Due today"
			     :deadline today)
		      (:name "Overdue"
			     :deadline past)
		      (:name "Due soon"
			     :deadline future)
		      (:name "Unimportant"
			     :todo ("SOMEDAY" "MAYBE" "CHECK" "TO-READ" "TO-WATCH")
			     :order 100)
		      (:name "Waiting..."
			     :todo "WAITING"
			     :order 98)
		      (:name "Scheduled earlier"
			     :scheduled past)))))))))
  :config
  (setq org-agenda-files (directory-files-recursively org-projects-dir "\\.org$"))
  (if (file-exists-p org-icalendar-file)
      (add-to-list 'org-agenda-files org-icalendar-file))
  (org-super-agenda-mode))

Contacts

https://www.reddit.com/r/emacs/comments/8toivy/tip_how_to_manage_your_contacts_with_orgcontacts/

(use-package org-contacts
  :after org
  :config
  (if (file-exists-p org-friends-file)
      (add-to-list 'org-contacts-files org-friends-file))
  (if (file-exists-p org-people-file)
      (add-to-list 'org-contacts-files org-people-file))
  )

Calendar and holidays

(use-package calendar
  :custom
  (diary-file (expand-file-name "diary" user-emacs-directory))
  (calendar-mark-holidays-flag t)
  (calendar-mark-diary-entries-flag t)
  (calendar-date-style 'iso))

French holidays, from https://irfu.cea.fr/Pisp/vianney.lebouteiller/emacs.html

;;French holidays
(setq french-holiday
      '((holiday-fixed 1 1 "Jour de l'an")
        (holiday-fixed 5 8 "Victoire 45")
        (holiday-fixed 7 14 "Fête nationale")
        (holiday-fixed 8 15 "Assomption")
        (holiday-fixed 11 1 "Toussaint")
        (holiday-fixed 11 11 "Armistice 18")
        (holiday-easter-etc 1 "Lundi de Pâques")
        (holiday-easter-etc 39 "Ascension")
        (holiday-easter-etc 50 "Lundi de Pentecôte")
        (holiday-fixed 1 6 "Épiphanie")
        (holiday-fixed 2 2 "Chandeleur")
        (holiday-fixed 2 14 "Saint Valentin")
        (holiday-fixed 5 1 "Fête du travail")
        (holiday-fixed 5 8 "Commémoration de la capitulation de l'Allemagne en 1945")
        (holiday-fixed 6 21 "Fête de la musique")
        (holiday-fixed 11 2 "Commémoration des fidèles défunts")
        (holiday-fixed 12 25 "Noël")
        ;; fêtes à date variable
        (holiday-easter-etc 0 "Pâques")
        (holiday-easter-etc 49 "Pentecôte")
        (holiday-easter-etc -47 "Mardi gras")
        (holiday-float 6 0 3 "Fête des pères") ;; troisième dimanche de juin
        ;; Fête des mères
        (holiday-sexp
         '(if (equal
               ;; Pentecôte
               (holiday-easter-etc 49)
               ;; Dernier dimanche de mai
               (holiday-float 5 0 -1 nil))
              ;; -> Premier dimanche de juin si coïncidence
              (car (car (holiday-float 6 0 1 nil)))
            ;; -> Dernier dimanche de mai sinon
            (car (car (holiday-float 5 0 -1 nil))))
         "Fête des mères")))

(setq calendar-holidays (append french-holiday)
      calendar-mark-diary-entries-flag nil) ;calendar-mark-holidays-flag t

Org-babel

(with-eval-after-load 'org
  (setq org-confirm-babel-evaluate nil)
  (setq org-src-fontify-natively t)
  (setq org-src-preserve-indentation t)
  (setq org-src-persistent-message nil)
  (setq org-src-window-setup 'current-window)

  (org-babel-do-load-languages 'org-babel-load-languages
                               '(
                                 (C . t)
                                 (ditaa . t)
                                 (emacs-lisp . t)
                                 (latex . t)
                                 (plantuml . t)
                                 (python . t)
                                 (shell . t)
                                 ))
  (setq org-ditaa-jar-path "/usr/bin/ditaa")
  )

Org-Latex

(with-eval-after-load 'ox-latex
  (setq org-latex-hyperref-template nil)
  (setq org-latex-listings 'minted)
  (setq org-latex-minted-options
	'(("mathescape" "true")
	  ("escapeinside" "@@")
	  ("breaklines" "true")
	  ("fontsize" "\\tiny")))
  (setq org-latex-compiler "xelatex")
  (defcustom org-latex-minted-from-org-p 't
    "If non-nil, then included minted in `org-latex-packages-alist'
      and get options from `org-latex-minted-options'."
    :type 'boolean
    :group 'org-export-latex
    :version "26.1"
    :package-version '(Org . "9.0"))

  (defun org-latex-toggle-minted-from-org ()
    "Toggle `org-latex-minted-from-org-p'."
    (interactive)
    (cl-flet ((nominted (pkg) (not (string= (cadr pkg) "minted"))))
      (if (not org-latex-minted-from-org-p)
          (setq org-latex-packages-alist
                (append org-latex-packages-alist '(("newfloat" "minted"))))
        (setq org-latex-packages-alist (seq-filter #'nominted org-latex-packages-alist)))
      (setq org-latex-minted-from-org-p (not org-latex-minted-from-org-p))
      (message "org minted %s" (if org-latex-minted-from-org-p
                                   "enabled" "disabled"))))
  ;; Latex process
  (setq oxl-process-bibtex
        '("latexmk -pdflatex='pdflatex -interaction=nonstopmode -shell-escape' -synctex=1 -pdf -bibtex -f %f"))

  (setq oxl-process-biber
        '("latexmk -pdflatex='pdflatex -interaction=nonstopmode -shell-escape' -synctex=1 -pdf -biber -f %f"))

  (setq oxl-process-xelatex
        '("latexmk -pdf -shell-escape -xelatex -f %f"))

  (setq oxl-process-lualatex
        '("latexmk -pdf -synctex=1 -shell-escape -lualatex -f %f"))

  (defcustom org-latex-pdf-engines
    '(("lualatex" . oxl-process-lualatex)
      ("xelatex" . oxl-process-xelatex)
      ("pdflatex" . (oxl-process-bibtex oxl-process-biber)))
    "A list of LaTeX commands available to run when
      `org-latex-export-to-pdf' is invoked."
    :type '(choice (cons string symbol) (cons string (repeat symbol)))
    :group 'org-export-latex
    :version "26.1")

  (defvar org-latex-pdf-process-hook nil
    "Hook to run after setting pdf process.")

  (defun org-latex-pdf-process-set (compiler)
    (interactive
     (list (completing-read "Compiler: " org-latex-pdf-engines)))
    (if (member compiler org-latex-compilers)
        (let ((process (cdr (assoc compiler org-latex-pdf-engines))))
          (setq org-latex-pdf-process (symbol-value
                                       (if (listp process)
                                           (intern (completing-read "Process:" process))
                                         process))
                org-latex-compiler compiler)
          (run-hooks org-latex-pdf-process-hook))
      (error "%s not in `org-latex-compilers'" compiler)))
  (setq org-latex-logfiles-extensions
        (append org-latex-logfiles-extensions
                '("acn" "ind" "ilg" "ist" "glo" "tex" "synctex.gz")))
  )

(with-eval-after-load 'ox
  (org-latex-pdf-process-set org-latex-compiler))

org links

Store org-links from magit:

M-x org-link-store   # From a magit buffer
M-x org-insert-link  # In the org file

This package is quite slow to load, force defer.

(use-package orgit
  :after org magit
  :defer t)
(use-package orgit-forge
  :after org forge)

Org-modern

(use-package org-modern
  :after org
  :defer t
  :custom
  ;; Choose some fonts
  (set-face-attribute 'default nil :family "Iosevka")
  (set-face-attribute 'variable-pitch nil :family "Iosevka Aile")
  (set-face-attribute 'org-modern-symbol nil :family "Iosevka")
  ;; :if window-system
  :hook (org-mode . org-modern-mode))

Org-sidebar

For a nice org-mode outline.

(use-package org-sidebar
  :after org
  :defer t)

Org-plugins

Useful for org-collector

(use-package org-contrib
  :after org)

mermaid

(use-package mermaid-mode
  :defer t)
(use-package ob-mermaid
  :after org
  :defer t
  :config
  (setq ob-mermaid-cli-path "~/opt/node_modules/.bin/mmdc"))

gnuplot

(use-package gnuplot
  :defer t)

latex

(use-package latex
  :ensure auctex
  :mode
  ("\\.tex\\'" . latex-mode)
  :bind
  (:map LaTeX-mode-map
        ("C-c C-r" . reftex-query-replace-document)
        ("C-c C-g" . reftex-grep-document))
  :config
  (setq-default TeX-master nil ; by each new file AUCTEX will ask for a master fie.
                TeX-PDF-mode t
                TeX-engine 'xetex)     ; optional

  (setq TeX-auto-save t
        TeX-save-query nil       ; don't prompt for saving the .tex file
        TeX-parse-self t
        TeX-show-compilation nil  ; if `t`, automatically shows compilation log
        LaTeX-babel-hyphen nil  ; Disable language-specific hyphen insertion.
        )
  (add-hook 'LaTeX-mode-hook 'reftex-mode)
  ;; Add standard Sweave file extensions to the list of files recognized  by AuCTeX.
  (add-hook 'TeX-mode-hook (lambda () (reftex-isearch-minor-mode)))
  )

Pandoc

(use-package ox-pandoc
  :disabled
  :after (:all ox)
  :custom
  (org-pandoc-options '((standalone . t)))
  :demand t
  :config
  (defun ox-pandoc--pdf-engine ()
    "Set the default latex pdf engine to the one set by `org-latex-pdf-process'. "
    (let ((syms (mapcar (lambda (x) (if (listp x) (if (listp (cdr x)) (cadr x) (cdr x)))) org-latex-pdf-engines))
          (pred (lambda (sym) (eq (symbol-value sym) org-latex-pdf-process)))
          (prefix "oxl-process-"))
      (cadr (split-string (symbol-name (car (seq-filter pred syms))) prefix))))

  (setq org-pandoc-options-for-beamer-pdf
        `((pdf-engine . ,(ox-pandoc--pdf-engine)))
        org-pandoc-options-for-latex-pdf
        `((pdf-engine . ,(ox-pandoc--pdf-engine))))

  (defun org-pandoc-pdf-engine-set (compiler)
    "Set the latex pdf engine for `org-pandoc-export-to-latex-pdf'."
    (interactive
     (list (completing-read "Compiler: " org-latex-compilers)))
    (setq org-pandoc-options-for-beamer-pdf
          `((pdf-engine . ,compiler))
          org-pandoc-options-for-latex-pdf
          `((pdf-engine . ,compiler))))
  ;; Open MS .doc?x files with system viewer.
  (when (symbolp 'org-file-apps)
    (add-to-list 'org-file-apps '("\\.docx?\\'" . system))))

ref

(use-package citar
  :no-require
  :if (file-exists-p org-roam-bibfile)
  :defer t
  :bind (("C-c n o" . citar-open)
         ("C-c r" . citar-insert-citation)
         :map minibuffer-local-map
         ("M-b" . citar-insert-preset))
  :custom
  (org-cite-global-bibliography org-roam-bibfile)
  (org-cite-insert-processor 'citar)
  (org-cite-follow-processor 'citar)
  (org-cite-activate-processor 'citar)
  (org-cite-csl-styles-dir
   (expand-file-name "~/Zotero/styles/"))
  (citar-bibliography org-cite-global-bibliography))

(use-package citar-embark
  :after citar embark
  :no-require
  :config (citar-embark-mode))

(use-package citar-org-roam
  :after citar org-roam
  :if (file-exists-p org-roam-bibfile)
  :no-require
  :custom
  (citar-org-roam-subdir "resource/references")
  :config
  (citar-org-roam-mode))

Roam

For zettelkasten notes.

Requires:

  • sqlite3
  • graphviz for dot

From https://systemcrafters.net/build-a-second-brain-in-emacs/capturing-notes-efficiently/

(use-package org-roam
  :if (file-directory-p org-roam-directory)
  :init
  (setq org-roam-v2-ack t)
  :custom
  (org-roam-completion-everywhere t)
  (org-roam-capture-templates
   '(("d" "default" plain "%?"
      :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n")
      :unnarrowed t)
     ("p" "person" plain "* ${title}%?\n:PROPERTIES:\n:POSITION:\n:EMAIL:\n:ID: %(shell-command-to-string \"uuidgen\")\n:END:"
      :if-new (file+head "people.org"
                         "#+title: Contacts\n#+date: %U\n#+filetags: :people:\n# -*- mode: Org; org-use-property-inheritance: (\"Company\") -*-\n* To Sort")
      :unnarrowed t)
     ("w" "Work project" plain "* Goals\n\n%?\n\n* Tasks\n\n** TODO Add initial tasks\n\n* Dates\n\n"
      :if-new (file+head "projects/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+category: ${title}\n#+filetags: :Project:\n")
      :unnarrowed t)
     ("i" "inbox" plain "* %?\n:PROPERTIES:\n:CREATED:%U\n:END:\n\n%i\n\nFrom: %a"
      :if-new (file+head "Inbox.org" "#+title: Inbox\n")
      :immediate-finish t)

     ("f" "friend" entry "* ${title}%?\n:PROPERTIES:\n:BIRTHDAY: %^{YYYY-MM-DD}t\n:NICKNAME:\n:GROUP:\n:EMAIL:\n:ADDRESS:\n:END:"
      :target (file+head "home/friends.org"
                         "#+title: Friends and Family\n#+date: %U\n#+filetags: :people:#home:\n")
      :unnarrowed t)
     ("h" "home" plain "%?"
      :if-new (file+head "home/%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n")
      :unnarrowed t)
     ("P" "Home project" plain "* Goals\n\n%?\n\n* Tasks\n\n** TODO Add initial tasks\n\n* Dates\n\n"
      :if-new (file+head "home/projects/${slug}.org" "#+title: ${title}\n#+category: ${title}\n#+filetags: :Project:#home:\n")
      :unnarrowed t)
     )
   )
  :bind (("C-c n l" . org-roam-buffer-toggle)
         ("C-c n f" . org-roam-node-find)
         ("C-c n i" . org-roam-node-insert)
         ("C-c n I" . org-roam-node-insert-immediate)
         ("C-c n t" . (lambda () "Populate inbox"
			(interactive)
			(org-roam-capture nil "i")))
         ("C-c n T" . org-roam-dailies-capture-today)
         ("C-c n d" . org-roam-dailies-goto-today)
         :map org-mode-map
         ("C-M-i" . completion-at-point)
         :map org-roam-dailies-map
         ("Y" . org-roam-dailies-capture-yesterday)
         ("T" . org-roam-dailies-capture-tomorrow))
  :bind-keymap
  ("C-c n d" . org-roam-dailies-map)
  :config

  (require 'org-roam-dailies) ;; Ensure the keymap is available
  (org-roam-db-autosync-mode)

   (defun my/org-roam-copy-todo-to-today ()
     (interactive)
     (let ((org-refile-keep t) ;; Set this to nil to delete the original!
           (org-roam-dailies-capture-templates
            '(("t" "tasks" entry "%?"
               :if-new (file+head+olp "%<%Y-%m-%d>.org" "#+title: %<%Y-%m-%d>\n" ("Tasks")))))
           (org-after-refile-insert-hook #'save-buffer)
           today-file
           pos)
       (save-window-excursion
	 (org-roam-dailies--capture (current-time) t)
	 (setq today-file (buffer-file-name))
	 (setq pos (point)))

       ;; Only refile if the target file is different than the current file
       (unless (equal (file-truename today-file)
                      (file-truename (buffer-file-name)))
	 (org-refile nil nil (list "Tasks" today-file nil pos)))))

   (add-to-list 'org-after-todo-state-change-hook
		(lambda ()
		  (when (equal org-state "DONE")
                    (my/org-roam-copy-todo-to-today))))
  )

Zotero

Follow http://www.mkbehr.com/posts/a-research-workflow-with-zotero-and-org-mode/

;; (use-package org-noter)
(use-package zotxt)

French

Save

From https://github.com/KaratasFurkan/.emacs.d/blob/emacs-29/README.org#synchronizing-changes

(defun cc/tangle-config ()
  "Export code blocks from the literate config file asynchronously."
  (interactive)
  (make-process
   :command `("emacs" ,config-org "--batch" "--eval"
              ,(format "(org-babel-tangle nil \"%s\" \"emacs-lisp\")" config-el))
   :name "tangle-process"
   :filter (lambda (process output) (message (string-trim output)))))

;; prevent emacs from killing itself until the tangle-process finished
(add-to-list 'kill-emacs-query-functions
             (lambda ()
               (or (not (process-live-p (get-process "tangle-process")))
                   (y-or-n-p "\"fk/tangle-config\" is running; kill it? "))))

New packages to look

Releases

No releases published

Packages

No packages published