- Lexical-biding
- Auto-tangle Configuration file
- Emacs Cache and Temporary Files
- Default Config
- Which-key
- General keybindings
- Evil mode and Keybindings
- Kanagawa
- Doom modeline
- Undo
- Org
- Dashboard
- Centaur Tabs
- Treesitter
- Eglot and Mason
- Completion
- WS butler
- Eat (Emulate A Terminal)
- Dired and Divirsh
Gives better performance, lexial closures, and code safety, allowing local variables to remain truly local.
;; -*- lexical-binding: t; -*-Auto-Tangle Org configuration file for better starup times, it refreshes the package-quickstart file.
(defun start/org-babel-tangle-config ()
"Automatically tangle init.org config and refresh package-quickstart"
(interactive)
(when (string-equal (file-name-directory (buffer-file-name))
(expand-file-name user-emacs-directory))
;; Dynamic scoping to the rescue
(let ((org-confirm-babel-evaluate nil))
(org-babel-tangle)
(package-quickstart-refresh))))
(add-hook 'org-mode-hook (lambda ()
(add-hook 'after-save-hook #'start/org-babel-tangle-config)))A macro that allows you to isolate package configuration in your .emacs in a way that is both-performance-oriented and, whell, tidy.
With Emacs 29 use-package is now built-in.
(require 'use-package-ensure)
(setq use-package-always-ensure t);; Configure the 'foo' package
;; You can also use (use-package emacs) to customize Emacs with use-package.
(use-package foo
:init (message "Before") ;; execute code Before a package is loaded.
:config (message "After") ;; execute code After a package is loaded.
:custom (foovar t) ;; Customization of package custom variables same as setq.
:ensure t ;; Ensure the package is installed if it's not already.
;; These are also used for lazy loading.
;; Don't load the package until these are not true.
:bind ("C-." . myfunc) ;; Defer package loading until keybindings are invoked.
:after (mypackage) ;; Load package after specified packages have been loaded.
;; If you don't know what a hook is:
;; C-h i: g for goto-node: Type (emacs)Hooks
:hook (myhook . myfunc) ;; Add functions to specified hooks when the package is loaded.
:command (bar) ;; Define commands provided by the package to be lazy-loaded.
:defer t ;; Only load this package if it's explicitly needed or a command/hook associated with it is called.
;; Install package with package.el from source.
:vc (:url "<You git repo url>"
:branch "main"
:rev :newest) ;; Use latest commit
)Like Linux distributions, Emacs uses repositories to manage its packages.
(setq package-archives '(("melpa" . "https://melpa.org/packages/") ;; Sets default package repositories
("elpa" . "https://elpa.gnu.org/packages/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")))Improves startup times by allowing Emacs to precompute and generate a single, large autoload file. Instead of re-computing them on every startup.
Package quickstart only works with package.el.
(setq package-quickstart t) ;; For blazingly fast startup times, this line makes startup miles faster(defcustom my/cache-directory
(expand-file-name "emacs/" "~/.cache")
"Base directory for Emacs cache files."
:type `(choice
(const :tag "Inside Emacs config (cache/ in user-emacs-directory)"
,(expand-file-name "emacs/" "~/.cache"))
(const :tag "System temp (/tmp/emacs-cache/)" "/tmp/emacs-cache/")
(directory :tag "Custom directory"))
:group 'my)
(when custom-file
(load custom-file 'noerror 'nomessage))
(defvar my/cache-paths
'(;; Files:
(bookmark-file . "bookmarks")
(ielm-history-file-name . "ielm-history.eld")
(project-list-file . "projects")
(recentf-save-file . "recentf")
(savehist-file . "history")
(save-place-file . "saveplace")
(transient-history-file . "transient/history.el")
(transient-levels-file . "transient/levels.el")
(transient-values-file . "transient/values.el")
(tramp-persistency-file-name . "tramp")
(nsm-settings-file . "network-security.data")
;; Directories:
(auto-saves . "auto-saves/")
(auto-saves-sessions . "auto-saves/sessions/")
(multisession-directory . "multisession/")
(url-configuration-directory . "url/")
(image-dired-dir . "image-dired/")
(erc-log-channels-directory . "erc/logs/")
(erc-image-cache-directory . "erc/images/")
(rcirc-log-directory . "rcirc/logs/"))
"Alist of (KEY . RELATIVE-PATH) for cache locations.")
(defun my/cache--path (key)
"Return the absolute path for KEY in `my/cache-paths'."
(let ((rel (cdr (assq key my/cache-paths))))
(unless rel
(error "my/cache--path: Unknown key %S" key))
(expand-file-name rel my/cache-directory)))
(defun my/cache--ensure-dirs ()
"Create every directory referenced by `my/cache-paths'."
(dolist (entry my/cache-paths)
(let* ((abs (my/cache--path (car entry)))
(dir (if (directory-name-p abs)
abs
(file-name-directory abs))))
(make-directory dir t))))
(my/cache--ensure-dirs)(use-package emacs
:init
(menu-bar-mode -1)
(tool-bar-mode -1)
(scroll-bar-mode -1)
(global-display-line-numbers-mode t)
(global-hl-line-mode t)
(electric-pair-mode t)
(electric-indent-mode -1)
(global-auto-revert-mode t)
(set-frame-font "JetBrainsMono Nerd Font Mono 14" nil t)
:custom
;; cleaning cache
(bookmark-file (my/cache--path 'bookmark-file))
(ielm-history-file-name (my/cache--path 'ielm-history-file-name))
(project-list-file (my/cache--path 'project-list-file))
(recentf-save-file (my/cache--path 'recentf-save-file))
(savehist-file (my/cache--path 'savehist-file))
(save-place-file (my/cache--path 'save-place-file))
(transient-history-file (my/cache--path 'transient-history-file))
(transient-levels-file (my/cache--path 'transient-levels-file))
(transient-values-file (my/cache--path 'transient-values-file))
(nsm-settings-file (my/cache--path 'nsm-settings-file))
(multisession-directory (my/cache--path 'multisession-directory))
(url-configuration-directory (my/cache--path 'url-configuration-directory))
(create-lockfiles nil)
(make-backup-files nil)
(auto-save-default t)
(mouse-wheel-progressive-speed nil)
(scroll-conservatively 10)
(scroll-margin 8)
(use-short-answers t)
(treesit-font-lock-level 4)
(dired-kill-when-opening-new-dired-buffer t)
(org-log-done 'time)
:config
(setq auto-save-list-file-prefix (my/cache--path 'auto-saves-sessions)
auto-save-file-name-transforms
`((".*" ,(my/cache--path 'auto-saves) t)))
(setopt tramp-persistency-file-name (my/cache--path 'tramp-persistency-file-name)))(use-package which-key
:init
(which-key-mode 1)
:custom
(which-key-idle-delay 0.3))(use-package general
:config
(general-create-definer start/leader-keys
:keymaps 'override
:prefix ";"
:global-prefix ";")
(start/leader-keys
:keymaps 'normal
"w" '(save-buffer :wk "Save buffer")
"q" '(delete-window :wk "Close other windows")
"Q" '(delete-other-windows :wk "Close window")
"k" '(kill-buffer :wk "Kill buffer")
"f" '(projectile-find-file :wk "Find files")
"g" '(projectile-grep :wk "Search with grep")
"e" '(dired :wk "Open dired")
"r" '(switch-to-buffer :wk "Display buffers to select")
"d" '(dashboard-open :wk "Open dashboard")
"x" '(eat :wk "Toggle terminal emulator"))
(start/leader-keys
:keymaps 'normal
"b" '(:ignore t :wk "BUFFER")
"bb" '(switch-to-buffer :wk "Switch buffer")
"bk" '(kill-current-buffer :wk "Kill this buffer")
"bn" '(next-buffer :wk "Next buffer")
"bp" '(previous-buffer :wk "Previous buffer")
"br" '(revert-buffer :wk "Reload buffer"))
(start/leader-keys
:keymaps 'normal
"o" '(:ignore t :wk "ORG")
"os" '(org-store-link :wk "store link")
"oa" '(org-agenda :wk "open agenda")
"on" '(org-capture :wk "create new note"))
(start/leader-keys
:keymaps 'normal
"l" '(:ignore t :wk "EGLOT")
"le" '(eglot-reconnect :wk "Eglot Reconnect")
"ld" '(eldoc-doc-buffer :wk "Eldoc Buffer")
"lf" '(eglot-format :wk "Eglot Format")
"ln" '(flymake-goto-next-error :wk "Flymake next error")
"lp" '(flymake-goto-prev-error :wk "Flymake previous error")
"la" '(eglot-code-actions :wk "Eglot code actions")
"lr" '(eglot-rename :wk "Eglot Rename")
"li" '(xref-find-definitions :wk "Find definition")
"ls" '(xref-find-references :wk "Find references")
"lv" '(:ignore t :wk "Elisp")
"lvb" '(eval-buffer :wk "Evaluate elisp in buffer")
"lvr" '(eval-region :wk "Evaluate elisp in region"))
)(use-package evil
:hook (after-init . evil-mode)
:init
(evil-mode)
:config
(evil-set-initial-state 'eat-mode 'insert) ;; Set initial state in eat terminal to insert mode
(define-key evil-normal-state-map (kbd "C-e") 'evil-scroll-up)
(define-key evil-normal-state-map (kbd "s") nil)
(define-key evil-normal-state-map (kbd "h") nil)
(define-key evil-normal-state-map (kbd "j") nil)
(define-key evil-normal-state-map (kbd "k") nil)
(define-key evil-normal-state-map (kbd "l") nil)
(define-key evil-normal-state-map (kbd "ss") 'evil-window-split)
(define-key evil-normal-state-map (kbd "sv") 'evil-window-vsplit)
(define-key evil-normal-state-map (kbd "h") 'evil-window-left)
(define-key evil-normal-state-map (kbd "j") 'evil-window-down)
(define-key evil-normal-state-map (kbd "k") 'evil-window-up)
(define-key evil-normal-state-map (kbd "l") 'evil-window-right)
(global-set-key [C-backspace] 'evil-delete-backward-word) ;; Make C-backspace less agressive
:custom
(evil-want-keybinding nil) ;; Disable evil bindings in other modes (It's not consistent and not good)
(evil-want-C-u-scroll t) ;; Set C-u to scroll up
(evil-want-C-i-jump nil) ;; Disables C-i jump
(evil-undo-system 'undo-redo) ;; C-r to redo
(evil-want-fine-undo t)
;; (evil-respect-visual-line-mode t) ;; Move in wrap lines
;; Unmap keys in 'evil-maps. If not done, org-return-follows-link will not work
:bind (:map evil-motion-state-map
("SPC" . nil)
("RET" . nil)
("TAB" . nil)))
(use-package evil-collection
:after evil
:config
;; Setting where to use evil-collection)
(setq evil-collection-mode-list '(dired ibuffer magit corfu consult info (package-menu package) bookmark dashboard))
(evil-collection-init))
(use-package evil-commentary
:after evil
:config
(evil-commentary-mode 1))(use-package kanagawa-themes
:config
(add-to-list 'default-frame-alist '(alpha-background . 95))
(load-theme 'kanagawa-wave t))(use-package doom-modeline
:init (doom-modeline-mode 1))(use-package undo-fu-session
:config
(setq undo-fu-session-directory (expand-file-name "undo-fu-session/" user-emacs-directory))
(setq undo-limit 67108864) ; 64mb
(setq undo-strong-limit 100663296) ; 96mb
(setq undo-outer-limit 1006632960) ; 960mb
(undo-fu-session-global-mode))(use-package org
:ensure t
:bind
("C-c c" . org-capture)
:config
(setq org-agenda-files '("~/Documentos/org/task.org"))
(setq org-capture-templates
'(("t" "Todo" entry (file+headline "~/Documentos/org/task.org" "Tasks")
"* TODO %?\n %i\n %a")
("j" "Journal" entry (file+datetree "~/Documentos/org/journal.org")
"* %?\nEntered on %U\n %i\n %a")
("n" "Note (Type Subject)" entry
(file (lambda () (format "~/Documentos/org/%s.org" (read-string "Subject: "))))
""))))(use-package org-superstar
:after org
:custom
(org-hide-emphasis-markers t)
(org-pretty-entities t)
(org-agenda-tags-column 0)
(org-ellipsis "")
:hook ((org-mode . org-superstar-mode) (org-mode . auto-fill-mode))) (use-package org-contrib
:after org
:config
(org-babel-do-load-languages
'org-babel-load-languages
'((vala . t)
(python . t))))(use-package toc-org
:commands toc-org-enable
:init (add-hook 'org-mode-hook 'toc-org-enable))Org-tempo is not a separe package but a module within org that can be enabled. Org-tempo allow for ‘<s’ followed by TAG to expand to a begin_src tag.
| Typing the bellow + TAB | Expands to … |
|---|---|
<a | #+BEGIN_EXPORT ascii |
<c | #+BEGIN_CENTER |
<e | #+BEGIN_COMMENT |
<E | #+BEGIN_EXPORT |
<h | #+BEGIN_EXPORT html |
<l | #+BEGIN_EXPORT latex |
<q | #+BEGIN_QUOTE |
<s | #+BEGIN_SRC |
<v | #+BEGIN_VERSE |
(require 'org-tempo)(use-package projectile
:init
(setq projectile-project-search-path '("~/Github/" "~/Documentos/" "~/.config"))
(setq projectile-cleanup-known-projects nil)
:config
(projectile-mode))
(use-package dashboard
:ensure t
:config
(dashboard-setup-startup-hook)
(setq dashboard-items '((recents . 5)
(projects . 5)
(agenda . 10)))
(setq dashboard-projects-backend 'projectile)
(setq dashboard-display-icons-p t)
(setq dashboard-icon-type 'nerd-icons)
(setq dashboard-set-heading-icons t)
(setq dashboard-set-file-icons t)
(setq dashboard-startup-banner '(1 2 3 logo))
(setq dashboard-banner-logo-title "Success is the sum of small efforts, repeated day in and day out.")
(setq dashboard-footer-messages
'(
"Emacs: An operating system that happens to have a text editor."
"Opening Emacs is the first step. Closing it is the final boss."
"Configuring Emacs is not procrastination, it's 'Workflow Engineering'."
"Your Org-mode habits are watching you. Go study Math!"
"E.M.A.C.S. - Eight Megabytes And Constantly Swapping (circa 1985)."
"Emacs is not a religion. It's just the only true way to live."
"Stop staring at this dashboard and M-x compile your C++ code!"))
(setq dashboard-set-navigator t)) (use-package centaur-tabs
:demand
:config
(centaur-tabs-mode t)
:bind
("C-<up>" . centaur-tabs-ace-jump)
("C-<left>" . centaur-tabs-backward)
("C-<right>" . centaur-tabs-forward)
("C-<down>" . kill-current-buffer)
)(use-package treesit-auto
:after emacs
:custom
(treesit-auto-install 'prompt)
:config
(treesit-auto-add-to-auto-mode-alist 'all)
(global-treesit-auto-mode t))(use-package eglot
:ensure nil ;; 'nil' porque já vem embutido no Emacs 29+
:hook
((js-mode
tsx-ts-mode
typescript-ts-base-mode ;; Enable LSP for TypeScript
css-mode ;; Enable LSP for CSS
go-ts-mode ;; Enable LSP for Go
js-ts-mode ;; Enable LSP for JavaScript (TS mode)
prisma-mode ;; Enable LSP for Prisma
ruby-base-mode ;; Enable LSP for Ruby
rust-ts-mode ;; Enable LSP for Rust
html-ts-mode) . eglot-ensure)
:custom
(eglot-events-buffer-size 0) ;; No event buffers (LSP server logs)
(eglot-autoshutdown t);; Shutdown unused servers.
(eglot-report-progress nil))
;; Package manager for LSP, DAP, linters, and more for the Emacs Operating System.
(use-package mason
:hook (after-init . mason-ensure))
;; Show flymake errors with sideline.
(use-package sideline-flymake
:hook (flymake-mode . sideline-mode)
:custom
(flymake-fringe-indicator-position nil)
(flymake-margin-indicator-position nil)
(sideline-flymake-display-mode 'line) ;; Show errors on the current line
(sideline-backends-right '(sideline-flymake)))(use-package corfu
;; Optional customizations
:custom
(corfu-cycle t) ;; Enable cycling for `corfu-next/previous'
(corfu-auto t) ;; Enable auto completion
(corfu-auto-prefix 2) ;; Minimum length of prefix for auto completion.
(corfu-popupinfo-mode t) ;; Enable popup information
(corfu-popupinfo-delay 0.5) ;; Lower popup info delay to 0.5 seconds from 2 seconds
(corfu-separator ?\s) ;; Orderless field separator, Use M-SPC to enter 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 'prompt) ;; Preselect the prompt
;; (corfu-on-exact-match nil) ;; Configure handling of exact matches
;; (corfu-scroll-margin 5) ;; Use scroll margin
(completion-ignore-case t)
;; Emacs 30 and newer: Disable Ispell completion function.
;; Try `cape-dict' as an alternative.
(text-mode-ispell-word-completion nil)
;; Enable indentation+completion using the TAB key.
;; `completion-at-point' is often bound to M-TAB.
(tab-always-indent 'complete)
(corfu-preview-current nil) ;; Don't insert completion without confirmation
;; Recommended: Enable Corfu globally. This is recommended since Dabbrev can
;; be used globally (M-/). See also the customization variable
;; `global-corfu-modes' to exclude certain modes.
:init
(global-corfu-mode))
(use-package nerd-icons-corfu
:after corfu
:init (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))(use-package orderless
:defer
:custom
(completion-styles '(orderless basic))
(completion-category-overrides '((file (styles basic partial-completion)))))(use-package vertico
:hook (after-init . vertico-mode)
;; Vim keybinds
;; :bind (:map vertico-map
;; ("C-j" . vertico-next)
;; ("C-k" . vertico-previous)
;; ("C-u" . vertico-scroll-down)
;; ("C-d" . vertico-scroll-up))
:custom
(vertico-cycle t) ;; Enable cycling for `vertico-next/previous'
)
(savehist-mode) ;; Enables save history mode
(use-package marginalia
:after vertico
:config
(marginalia-mode))
(use-package nerd-icons-completion
:after marginalia
:config
(nerd-icons-completion-mode)
:hook
(marginalia-mode . nerd-icons-completion-marginalia-setup))Removes whitespace from the ends of lines.
(use-package ws-butler
:hook (after-init . ws-butler-global-mode))(use-package eat
:defer
:hook ('eshell-load-hook #'eat-eshell-mode))Dirvish enhances Emacs’s builtin-in Dired mode, providing a visually appeling and highly customizable interface.
(use-package dired
:ensure nil
:config
(evil-define-key 'normal dired-mode-map
"a" #'dired-create-empty-file
"A" #'dired-create-directory
"d" #'dired-do-delete))
(use-package dirvish
:init
(dirvish-override-dired-mode)
:custom
(dirvish-attributes
'(vc-state subtree-state nerd-icons collapse file-time file-size)
dirvish-side-attributes
'(vc-state nerd-icons collapse file-size)))
(use-package nerd-icons)