34 KiB
rogs DOOM Emacs config
- Introduction
- Basic configuration
- Look and feel
- Org Mode + Org Roam
- Programming languages
- Custom
- Misc
Introduction
This configuration represents my personal Doom Emacs setup, focused on productivity, organization with Org-mode, and programming. The file is organized into logical sections, starting with basic settings, then appearance, followed by major functionality areas like Org-mode and programming language support.
Key principles in this configuration:
- Prioritize keyboard-driven workflows
- Integrate personal productivity systems through Org-mode
- Optimize for both writing and coding tasks
This document serves both as configuration and as documentation. Each section explains not just what the code does, but why it's important to my workflow. If you're new to Doom Emacs, you can use this as a reference for setting up your own configuration.
To navigate this file efficiently:
- Use `SPC n s` to search for specific settings
- Use `TAB` on headings to expand/collapse sections
- Look for the explanatory text before each code block
Basic configuration
This section contains fundamental identity settings that are used by various Emacs packages, particularly for version control systems like Git and for email clients. These settings ensure that my contributions are properly attributed.
First off, set my user and email
(setq user-full-name "Roger Gonzalez"
user-mail-address "roger@rogs.me")
Look and feel
This section configures the visual aspects of my Emacs experience. I prefer a clean, distraction-free interface with a dark theme that's easy on the eyes during long coding sessions. Font choices prioritize readability and support for programming ligatures.
Fonts
This works only in Linux. On MacOS we keep the default fonts.
(if (not (eq system-type 'darwin))
(progn
(setq doom-font (font-spec :family "MesloLGS Nerd Font" :size 14)
doom-variable-pitch-font (font-spec :family "sans")
doom-big-font (font-spec :family "MesloLGS Nerd Font" :size 24))))
Theme
(after! doom-themes
(setq doom-themes-enable-bold t
doom-themes-enable-italic t))
(custom-set-faces!
'(font-lock-comment-face :slant italic)
'(font-lock-keyword-face :slant italic))
(setq doom-theme 'doom-badger)
(setq fancy-splash-image "~/.config/doom/logo.png")
Misc
Display relative numbers on the buffer
(setq display-line-numbers-type 'relative)
Org Mode + Org Roam
The cornerstone of my productivity system. My entire life is managed through Org Mode and Org Roam, from task management and note-taking to project planning and knowledge management. This extensive configuration reflects years of refinement to match my personal workflow.
The setup includes custom agenda views, capture templates, and todo states that implement a GTD-inspired system with my own modifications for different types of tasks and projects.
Key components of this system:
- Custom TODO states that reflect my workflow (NEXT, WAITING, SOMEDAY, etc.)
- Visual styling to quickly identify task states and priorities
- Capture templates for different types of information
- Custom agenda views for different perspectives on my tasks
- Recurring task handling with org-recur
- ID-based linking for creating a personal knowledge graph
This section is organized into logical subsections, each focusing on a specific aspect of the Org Mode configuration. The most frequently used features are placed earlier in the file.
Set the directory
(setq org-directory "~/org/")
(setq org-roam-directory "~/roam/")
Basic Org Setup
This section contains the foundational settings for Org mode, including directory paths and basic behavior.
(after! org
;; Include diary
(setq org-agenda-include-diary t)
;; Enforce ordered tasks
(setq org-enforce-todo-dependencies t)
(setq org-enforce-todo-checkbox-dependencies t)
(setq org-track-ordered-property-with-tag t)
;; Text formatting
(add-hook 'org-mode-hook #'auto-fill-mode)
(setq-default fill-column 105)
;; Save all org buffers on each save
(add-hook 'auto-save-hook 'org-save-all-org-buffers)
(add-hook 'after-save-hook 'org-save-all-org-buffers)
(require 'org-download)
(add-hook 'dired-mode-hook 'org-download-enable)
(add-hook 'org-mode-hook 'org-auto-tangle-mode))
Task Management
Configuration for task tracking, including TODO keywords, priorities, and logging behavior. This implements a GTD-inspired workflow with custom states to track different stages of task completion.
The TODO keywords are carefully chosen to represent distinct states in my workflow:
- REPEAT: Tasks that recur on a schedule
- NEXT: The immediate next actions I should focus on
- DELEGATED: Tasks I've assigned to someone else
- TODO: Standard tasks that need to be done
- WAITING: Tasks blocked by external factors
- SOMEDAY: Ideas or tasks for future consideration
- PROJ: Project containers that group related tasks
Priorities follow a simple decision matrix:
- A: Do it now (urgent and important)
- B: Decide when to do it (important but not urgent)
- C: Delegate it (urgent but not important)
- D: Just an idea (neither urgent nor important)
The logging configuration ensures I maintain a history of state changes, completion times, and notes about rescheduling.
(after! org
;; Logs
(setq org-log-state-notes-insert-after-drawers nil
org-log-into-drawer "LOGBOOK"
org-log-done 'time
org-log-repeat 'time
org-log-redeadline 'note
org-log-reschedule 'note)
;; TODO keywords and states
(setq-default org-todo-keywords
'((sequence "REPEAT(r)" "NEXT(n@/!)" "DELEGATED(e@/!)" "TODO(t@/!)"
"WAITING(w@/!)" "SOMEDAY(s@/!)" "PROJ(p)" "|"
"DONE(d@)" "CANCELLED(c@/!)" "FORWARDED(f@)")))
;; Priorities configuration
;; A: Do it now
;; B: Decide when to do it
;; C: Delegate it
;; D: Just an idea
(setq org-highest-priority ?A)
(setq org-lowest-priority ?D)
(setq org-default-priority ?B))
Visual Styling
Visual appearance settings for Org mode, including fonts, colors, and formatting.
(after! org
;; TODO keyword faces
(setq-default org-todo-keyword-faces
'(("REPEAT" . (:foreground "white" :background "indigo" :weight bold))
("NEXT" . (:foreground "red" :background "orange" :weight bold))
("DELEGATED" . (:foreground "white" :background "blue" :weight bold))
("TODO" . (:foreground "white" :background "violet" :weight bold))
("WAITING" (:foreground "white" :background "#A9BE00" :weight bold))
("SOMEDAY" . (:foreground "white" :background "#00807E" :weight bold))
("PROJ" . (:foreground "white" :background "deeppink3" :weight bold))
("DONE" . (:foreground "white" :background "forest green" :weight bold))
("CANCELLED" . (:foreground "light gray" :slant italic))
("FORWARDED" . (:foreground "light gray" :slant italic))))
;; Priority faces
(setq org-priority-faces '((?A . (:foreground "white" :background "dark red" :weight bold))
(?B . (:foreground "white" :background "dark green" :weight bold))
(?C . (:foreground "yellow"))
(?D . (:foreground "gray"))))
;; Headline styling
(setq org-fontify-done-headline t)
(setq org-fontify-todo-headline t)
;; Org bullets for prettier headings
(require 'org-bullets)
(add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))
Capture Templates
Templates for quickly capturing various types of information into Org mode.
(after! org
(setq org-capture-templates
(quote
(("G" "Define a goal" entry (file+headline "~/org/capture.org" "Capture")
(file "~/org/templates/goal.org") :empty-lines-after 1)
("R" "REPEAT entry" entry (file+headline "~/org/capture.org" "Capture")
(file "~/org/templates/repeat.org") :empty-lines-before 1)
("N" "NEXT entry" entry (file+headline "~/org/capture.org" "Capture")
(file "~/org/templates/next.org") :empty-lines-before 1)
("T" "TODO entry" entry (file+headline "~/org/capture.org" "Capture")
(file "~/org/templates/todo.org") :empty-lines-before 1)
("W" "WAITING entry" entry (file+headline "~/org/capture.org" "Capture")
(file "~/org/templates/waiting.org") :empty-lines-before 1)
("S" "SOMEDAY entry" entry (file+headline "~/org/capture.org" "Capture")
(file "~/org/templates/someday.org") :empty-lines-before 1)
("P" "PROJ entry" entry (file+headline "~/org/capture.org" "Capture")
(file "~/org/templates/proj.org") :empty-lines-before 1)
("B" "Book on the to-read-list" entry (file+headline "~/org/private.org" "Libros para leer")
(file "~/org/templates/book.org") :empty-lines-after 2)
("p" "Create a daily plan")
("pP" "Daily plan private" plain (file+olp+datetree "~/org/plan-free.org")
(file "~/org/templates/dailyplan.org") :immediate-finish t :jump-to-captured t)
("pL" "Daily plan Lazer" plain (file+olp+datetree "~/org/plan-lazer.org")
(file "~/org/templates/dailyplan.org") :immediate-finish t :jump-to-captured t)
("j" "Journal entry")
("jP" "Journal entry private" entry (file+olp+datetree "~/org/journal-private.org")
"** %U - %^{Heading}")
("jL" "Journal entry Lazer" entry (file+olp+datetree "~/org/journal-lazer.org")
"** %U - %^{Heading}")))))
Agenda Views
Custom agenda views for different perspectives on tasks and events.
(after! org
(setq org-agenda-custom-commands
(quote
(("A" . "Agendas")
("AT" "Daily overview"
((tags-todo "URGENT"
((org-agenda-overriding-header "Urgent Tasks")))
(tags-todo "RADAR"
((org-agenda-overriding-header "On my radar")))
(tags-todo "PHONE+TODO=\"NEXT\""
((org-agenda-overriding-header "Phone Calls")))
(tags-todo "COMPANY"
((org-agenda-overriding-header "Cuquitoni")))
(tags-todo "SHOPPING"
((org-agenda-overriding-header "Shopping")))
(tags-todo "Depth=\"Deep\"/NEXT"
((org-agenda-overriding-header "Next Actions requiring deep work")))
(agenda ""
((org-agenda-overriding-header "Today")
(org-agenda-span 1)
(org-agenda-start-day "1d")
(org-agenda-sorting-strategy
(quote
(time-up priority-down)))))
nil nil))
("AW" "Weekly overview" agenda ""
((org-agenda-overriding-header "Weekly overview")))
("AM" "Monthly overview" agenda ""
((org-agenda-overriding-header "Monthly overview"))
(org-agenda-span
(quote month))
(org-deadline-warning-days 0)
(org-agenda-sorting-strategy
(quote
(time-up priority-down tag-up))))
("W" . "Weekly Review Helper")
("Wn" "New tasks" tags "NEW"
((org-agenda-overriding-header "NEW Tasks")))
("Wd" "Check DELEGATED tasks" todo "DELEGATED"
((org-agenda-overriding-header "DELEGATED tasks")))
("Ww" "Check WAITING tasks" todo "WAITING"
((org-agenda-overriding-header "WAITING tasks")))
("Ws" "Check SOMEDAY tasks" todo "SOMEDAY"
((org-agenda-overriding-header "SOMEDAY tasks")))
("Wf" "Check finished tasks" todo "DONE|CANCELLED|FORWARDED"
((org-agenda-overriding-header "Finished tasks")))
("WP" "Planing ToDos (unscheduled) only" todo "TODO|NEXT"
((org-agenda-overriding-header "To plan")
(org-agenda-skip-function
(quote
(org-agenda-skip-entry-if
(quote scheduled)
(quote deadline))))))))))
Org Recur
Configuration for handling recurring tasks with org-recur.
(after! org
;; Load org-recur
(require 'org-recur)
(after! org-recur
(add-hook 'org-mode-hook #'org-recur-mode)
(add-hook 'org-agenda-mode-hook #'org-recur-agenda-mode)
(map! :map org-recur-mode-map
"C-c d" #'org-recur-finish)
(map! :map org-recur-agenda-mode-map
"C-c d" #'org-recur-finish
"C-c 0" #'org-recur-schedule-today)
(setq org-recur-finish-done t
org-recur-finish-archive t)))
Custom Org Functions
Custom functions to enhance Org mode functionality. These functions extend Org mode's capabilities to better support my specific workflow needs, including:
- Automatic agenda refreshing after rescheduling tasks
- Focus functions to filter agenda views by context
- Automatic ID generation for reliable linking between notes
- Clipboard functions for quick creation of Org links
- Checkbox reset functionality for recurring tasks
- Streamlined node insertion for Org-roam
These functions represent solutions to friction points I've encountered in my daily use of Org mode, making the system more efficient and tailored to my needs.
(after! org
;; Refresh org-agenda after rescheduling a task
(defun org-agenda-refresh ()
"Refresh all `org-agenda' buffers more efficiently."
(let ((agenda-buffers (seq-filter
(lambda (buf)
(with-current-buffer buf
(derived-mode-p 'org-agenda-mode)))
(buffer-list))))
(dolist (buffer agenda-buffers)
(with-current-buffer buffer
(org-agenda-maybe-redo)))))
(defadvice org-schedule (after refresh-agenda activate)
"Refresh org-agenda."
(org-agenda-refresh))
;; Focus functions
(defun org-focus (files msg)
"Set focus on specific org FILES with notification MSG."
(setq org-agenda-files files)
(message msg))
(defun org-focus-private ()
"Set focus on private things."
(interactive)
(org-focus '("~/org/private.org") "Focusing on private Org files"))
(defun org-focus-lazer ()
"Set focus on Lazer things."
(interactive)
(org-focus '("~/org/lazer.org") "Focusing on Lazer Org files"))
(defun org-focus-all ()
"Set focus on all things."
(interactive)
(org-focus '("~/org/") "Focusing on all Org files"))
;; ID management
(defun my/org-add-ids-to-headlines-in-file ()
"Add ID properties to all headlines in the current file which
do not already have one."
(interactive)
(org-map-entries 'org-id-get-create))
(add-hook 'org-mode-hook
(lambda ()
(add-hook 'before-save-hook
'my/org-add-ids-to-headlines-in-file nil 'local)))
(defun my/copy-idlink-to-clipboard ()
"Copy an ID link with the headline to killring.
If no ID exists, create a new unique ID. This function works only in
org-mode or org-agenda buffers.
The purpose of this function is to easily construct id:-links to
org-mode items. If its assigned to a key it saves you marking the
text and copying to the killring.
This function is a cornerstone of my note-linking workflow. It creates and copies
an org-mode ID link to the current heading, making it easy to reference content
across my knowledge base. I use this constantly when creating connections between
related notes or tasks."
(interactive)
(when (eq major-mode 'org-agenda-mode) ;if we are in agenda mode we switch to orgmode
(org-agenda-show)
(org-agenda-goto))
(when (eq major-mode 'org-mode) ; do this only in org-mode buffers
(let* ((heading (nth 4 (org-heading-components)))
(id (org-id-get-create))
(link (format "[[id:%s][%s]]" id heading)))
(kill-new link)
(message "Copied %s to killring (clipboard)" link))))
(global-set-key (kbd "<f5>") 'my/copy-idlink-to-clipboard)
;; Checkbox handling
(defun org-reset-checkbox-state-maybe ()
"Reset all checkboxes in an entry if the `RESET_CHECK_BOXES' property is set."
(interactive "*")
(when (org-entry-get (point) "RESET_CHECK_BOXES")
(org-reset-checkbox-state-subtree)))
(defun org-checklist ()
(when (member org-state org-done-keywords) ;; org-state dynamically bound in org.el/org-todo
(org-reset-checkbox-state-maybe)))
(add-hook 'org-after-todo-state-change-hook 'org-checklist)
;; Org-roam functions
(defun org-roam-node-insert-immediate (arg &rest args)
"Insert a node immediately without the capture process."
(interactive "P")
(let ((args (cons arg args))
(org-roam-capture-templates
(list (append (car org-roam-capture-templates)
'(:immediate-finish t)))))
(apply #'org-roam-node-insert args))))
Programming languages
This section configures language-specific settings for the programming languages I use regularly. Each language has its own requirements for linting, formatting, and IDE-like features, which are handled through LSP where possible.
My development workflow relies on having consistent tooling across different languages, with features like:
- Code completion and documentation
- Syntax checking and linting
- Formatting according to language standards
- Navigation and refactoring tools
LSP (Language Server Protocol) provides most of these features in a standardized way across languages, while language-specific configurations handle unique requirements for each language ecosystem.
LSP
(after! lsp-mode
(setq lsp-headerline-breadcrumb-enable t)
(setq lsp-headerline-breadcrumb-icons-enable t))
Python
(after! python
:init
(require 'auto-virtualenv)
(setq auto-virtualenv-global-dirs
'("~/.virtualenvs/" "~/.pyenv/versions/" "~/.envs/" "~/.conda/" "~/.conda/envs/" "./.venv"))
(add-hook 'python-mode-hook 'auto-virtualenv-setup)
(setq enable-local-variables :all)
(setq poetry-tracking-strategy 'projectile)
(setq cov-coverage-mode t)
(add-hook 'python-mode-hook 'cov-mode))
Groovy
(after! groovy-mode
(define-key groovy-mode-map (kbd "<f4>") 'my/jenkins-verify))
Go
(setq lsp-go-analyses '((shadow . t)
(simplifycompositelit . :json-false)))
RestClient
(setq restclient-same-buffer-response nil)
Custom
Here's where custom functionalities get configured.
Custom packages
These are additional packages that aren't part of the standard Doom modules but that I find essential for my workflow:
Package name | Description | URL |
---|---|---|
screenshot.el |
Good for taking screenshots directly in Emacs. | https://github.com/tecosaur/screenshot |
private.el |
This is a file for private values and API keys that shouldn't be in version control. | ./custom-packages/private.el.example . |
(add-to-list 'load-path "~/.config/doom/custom-packages")
(require 'screenshot)
(require 'private)
Custom functions
Update DOOM Emacs init.el file
This function brings up a comparison between the current init.el
file and the example file
(templates/init.example.el
). Very useful for upgrading manually.
More info here: https://github.com/doomemacs/doomemacs/issues/581#issuecomment-645448095
(defun my/ediff-init-and-example ()
"Compare init.el with the example init file."
(interactive)
(let ((init-file (concat doom-user-dir "init.el"))
(example-file (concat doom-emacs-dir "templates/init.example.el")))
(if (and (file-exists-p init-file)
(file-exists-p example-file))
(ediff-files init-file example-file)
(message "Cannot find init.el or example file"))))
(define-key! help-map "di" #'my/ediff-init-and-example)
HTTP Statuses
This is a custom helm command that displays all the HTTP status codes with their descriptions. As a developer working with web APIs, I frequently need to reference these codes. This function provides a quick, searchable reference without leaving Emacs or disrupting my workflow.
Usage: `M-x helm-httpstatus` or through the applications menu with `SPC a h`
(defvar helm-httpstatus-source
'((name . "HTTP STATUS")
(candidates . (("100 Continue") ("101 Switching Protocols")
("102 Processing") ("200 OK")
("201 Created") ("202 Accepted")
("203 Non-Authoritative Information") ("204 No Content")
("205 Reset Content") ("206 Partial Content")
("207 Multi-Status") ("208 Already Reported")
("300 Multiple Choices") ("301 Moved Permanently")
("302 Found") ("303 See Other")
("304 Not Modified") ("305 Use Proxy")
("307 Temporary Redirect") ("400 Bad Request")
("401 Unauthorized") ("402 Payment Required")
("403 Forbidden") ("404 Not Found")
("405 Method Not Allowed") ("406 Not Acceptable")
("407 Proxy Authentication Required") ("408 Request Timeout")
("409 Conflict") ("410 Gone")
("411 Length Required") ("412 Precondition Failed")
("413 Request Entity Too Large")
("414 Request-URI Too Large")
("415 Unsupported Media Type")
("416 Request Range Not Satisfiable")
("417 Expectation Failed") ("418 I'm a teapot")
("421 Misdirected Request")
("422 Unprocessable Entity") ("423 Locked")
("424 Failed Dependency") ("425 No code")
("426 Upgrade Required") ("428 Precondition Required")
("429 Too Many Requests")
("431 Request Header Fields Too Large")
("449 Retry with") ("500 Internal Server Error")
("501 Not Implemented") ("502 Bad Gateway")
("503 Service Unavailable") ("504 Gateway Timeout")
("505 HTTP Version Not Supported")
("506 Variant Also Negotiates")
("507 Insufficient Storage") ("509 Bandwidth Limit Exceeded")
("510 Not Extended")
("511 Network Authentication Required")))
(action . message)))
(defun helm-httpstatus ()
(interactive)
(helm-other-buffer '(helm-httpstatus-source) "*helm httpstatus*"))
Convert HTML to org
This function converts clipboard contents from HTML to Org format and then pastes (yanks) the result. It's extremely useful when researching online and wanting to capture formatted content directly into my org notes without losing structure.
Dependencies:
pandoc
for the format conversionxclip
for clipboard access
Usage: Press F4 in any org-mode buffer to convert and paste HTML from clipboard
(defun my/html2org-clipboard ()
"Convert HTML in clipboard to Org format and paste it."
(interactive)
(condition-case err
(progn
(kill-new (shell-command-to-string
"timeout 1 xclip -selection clipboard -o -t text/html | pandoc -f html -t json | pandoc -f json -t org --wrap=none"))
(yank)
(message "Pasted HTML in org"))
(error (message "Error converting HTML to Org: %s" (error-message-string err)))))
(after! org
(define-key org-mode-map (kbd "<f4>") 'my/html2org-clipboard))
My own menu
This is a custom menu for my own functions
(map! :leader
(:prefix-map ("a" . "applications")
:desc "HTTP Status cheatsheet" "h" #'helm-httpstatus)
(:prefix-map ("ao" . "org")
:desc "Org focus Lazer" "l" #'org-focus-lazer
:desc "Org focus private" "p" #'org-focus-private
:desc "Org focus all" "a" #'org-focus-all
))
Misc
Clipmon
Clipmon serves as my clipboard manager within Emacs. I chose it over alternatives like helm-clipboard
because it offers better integration with my workflow and provides automatic monitoring of clipboard changes. This allows me to maintain a history of copied text without manual intervention.
The configuration below sets up Clipmon to check the clipboard every second and makes the kill ring accessible through M-y with helm integration.
;; Ensure clipmon is loaded
(require 'clipmon)
(after! clipmon
(global-set-key (kbd "M-y") 'helm-show-kill-ring)
(add-to-list 'after-init-hook 'clipmon-mode-start)
(defadvice clipmon--on-clipboard-change (around stop-clipboard-parsing activate)
(let ((interprogram-cut-function nil)) ad-do-it))
(setq clipmon-timer-interval 1))
Git
Set delta
as the default magit diff
(add-hook 'magit-mode-hook (lambda () (magit-delta-mode +1)))
Accept pre-commit messages when creating git commits with magit-gptcommit mode
(defun my/magit-gptcommit-commit-accept-wrapper (orig-fun &rest args)
"Wrapper for magit-gptcommit-commit-accept to preserve original message."
(when-let ((buf (magit-commit-message-buffer)))
(with-current-buffer buf
(let ((orig-message (string-trim-right (or (git-commit-buffer-message) "") "\n$")))
(apply orig-fun args)
(unless (string-empty-p orig-message)
(save-excursion
(goto-char (point-min))
(insert orig-message)))))))
(advice-add 'magit-gptcommit-commit-accept
:around #'my/magit-gptcommit-commit-accept-wrapper)
LLM
This section configures various AI assistants and Large Language Model integrations. These tools augment my workflow by providing code suggestions, helping with documentation, and automating repetitive tasks like writing commit messages.
I use a combination of local models (via Ollama) and cloud services (OpenAI, Anthropic) depending on the task requirements and privacy considerations:
- GitHub Copilot: For real-time code suggestions while typing
- ChatGPT Shell: For general programming assistance and problem-solving
- Magit GPT: For automatically generating meaningful commit messages
- Forge LLM: For analyzing and summarizing GitHub issues and PRs
- Aider: For more complex code generation and refactoring tasks
Each tool has specific strengths, and I've configured them to complement each other in my development workflow. The API keys are stored in a separate private.el file for security.
LLM Menu
To streamline interaction with the various Large Language Model (LLM) tools integrated into my workflow, this section defines a dedicated menu accessible via the leader key. This provides quick, mnemonic access to frequently used AI assistants like Aider and ChatGPT Shell, avoiding the need for `M-x` and keeping these tools readily available.
The menu is bound to `SPC l` (for LLMs) and currently contains:
- `SPC l a`: Launches the Aidermacs transient menu (`aidermacs-transient-menu`).
- `SPC l c`: Launches the ChatGPT Shell transient menu (`chatgpt-shell-transient`).
(map! :leader
(:prefix-map ("l" . "LLMs")
:desc "Aidermacs" "a" #'aidermacs-transient-menu
:desc "ChatGPT Shell" "c" #'chatgpt-shell-transient))
ChatGPT Shell
(setq chatgpt-shell-model-version "gemini-2.5-pro-exp")
(setq chatgpt-shell-streaming "t")
(setq chatgpt-shell-system-prompt "You are a senior developer knowledgeable in every programming language")
(setq chatgpt-shell-openai-key openai-key)
(setq chatgpt-shell-google-key gemini-key)
(setq chatgpt-shell-anthropic-key anthropic-key)
(setq dall-e-shell-openai-key openai-key)
Magit GPT
(require 'llm-ollama)
(setq magit-gptcommit-llm-provider (make-llm-ollama :scheme "http" :host "192.168.0.122" :embedding-model "gemma3:12b" :chat-model "gemma3:12b"))
(setq llm-warn-on-nonfree nil)
(after! magit
(magit-gptcommit-mode 1)
(setq magit-gptcommit-prompt
"You are an expert programmer crafting a Git commit message. Carefully review the following file diffs as if you had read each line.
Your goal is to generate a commit message that follows the kernel Git commit style guide.
SUMMARY INSTRUCTIONS:
- Write a one-line summary of the change, no more than 50 characters.
- Use the imperative tense (for example, use 'Improve logging output' instead of 'Improved logging' or 'Improves logging').
- Do not include prefixes like Fix:, Feat:, or Chore: at the beginning of the summary.
- The summary must not end with a period.
- Ensure the summary reflects a single, specific, and cohesive purpose.
COMMENT INSTRUCTIONS:
- After the summary, write concise developer-facing comments explaining the commit.
- Each comment must be on its own line and prefixed with '-'.
- Each comment must end with a period.
- Do not include any paragraphs, introductions, or extra explanations.
- Do not use backticks (`) anywhere in the summary or comments.
- Do not use Markdown formatting (e.g., *, **, #, _, or inline code).
THE FILE DIFFS:
%s
Now, write the commit message in this exact format:
<summary line>
- comment1
- comment2
- commentN")
(magit-gptcommit-status-buffer-setup))
Forge LLM
(require 'forge-llm)
(forge-llm-setup)
(require 'llm-gemini)
(setq forge-llm-llm-provider (make-llm-gemini :key gemini-key :chat-model "gemini-2.5-pro-exp-03-25"))
(setq forge-llm-max-diff-size 'nil)
Github Copilot
;; Load copilot
(require 'copilot)
(after! copilot
(add-hook 'prog-mode-hook #'copilot-mode)
(map! :map copilot-completion-map
"<tab>" #'copilot-accept-completion
"TAB" #'copilot-accept-completion
"C-TAB" #'copilot-accept-completion-by-word
"C-<tab>" #'copilot-accept-completion-by-word))
Aider
(after! aidermacs
;; Set API keys
(setenv "ANTHROPIC_API_KEY" anthropic-key)
(setenv "OPENAI_API_KEY" openai-key)
(setenv "GEMINI_API_KEY" gemini-key)
(setenv "OLLAMA_API_BASE" ollama-api-base)
(setenv "OPENROUTER_API_KEY" openrouter-api-key)
;; General settings
(setq aidermacs-use-architect-mode t)
(setq aidermacs-default-model "openrouter/google/gemini-2.5-pro-exp-03-25:free")
(setq aidermacs-auto-commits nil)
(setq aidermacs-backend 'vterm)
(setq aidermacs-vterm-multiline-newline-key "S-<return>")
(add-to-list 'aidermacs-extra-args "--no-gitignore --chat-mode ask --no-auto-commits --cache-prompts --dark-mode --pretty --stream --vim --cache-keepalive-pings 2"))
Others
PlantUML
(setq plantuml-executable-path "/usr/bin/plantuml")
(setq plantuml-default-exec-mode 'executable)
(setq org-plantuml-exec-mode 'plantuml)
(setq plantuml-server-url 'nil)
(org-babel-do-load-languages 'org-babel-load-languages '((plantuml . t)))
(add-to-list 'auto-mode-alist '("\\.plantuml\\'" . plantuml-mode))
(setq org-babel-default-header-args:plantuml
'((:results . "verbatim") (:exports . "results") (:cache . "no")))
(after! org
(add-to-list 'org-src-lang-modes '("plantuml" . plantuml)))