#+TITLE: emacs config * suragu's Emacs config This is my Emacs configuration, if you don't like it, that's ok because I made it thinking of myself. Hopefully, the code here is tidy so anyone could modify it without great pain. ** Installation Just copy this repository to your emacs configuration path. Nothing else is needed. * Why? - I can - I don't like doom emacs - I don't like spacemacs - I don't want to learn doom emacs - I don't want to learn spacemacs - I don't like Vim * gc #+begin_src emacs-lisp ;; Minimize garbage collection during startup (setq gc-cons-threshold most-positive-fixnum) ;; Lower threshold back to 8 MiB (default is 800kB) (add-hook 'emacs-startup-hook (lambda () (setq gc-cons-threshold (expt 2 23)))) #+end_src * melpa crap, and basic packages installation melpa, where you get the packages. This also installs use-package, and other packages I use. #+BEGIN_SRC emacs-lisp (require 'package) (let* ((no-ssl (and (memq system-type '(windows-nt ms-dos)) (not (gnutls-available-p)))) (proto (if no-ssl "http" "https"))) ;; Comment/uncomment these two lines to enable/disable MELPA and MELPA Stable as desired (add-to-list 'package-archives (cons "melpa" (concat proto "://melpa.org/packages/")) t) ;;(add-to-list 'package-archives (cons "melpa-stable" (concat proto "://stable.melpa.org/packages/")) t) (when (< emacs-major-version 24) ;; For important compatibility libraries like cl-lib (add-to-list 'package-archives '("gnu" . (concat proto "://elpa.gnu.org/packages/"))))) (if (< emacs-major-version 27) (package-initialize)) (unless (package-installed-p 'use-package) (package-refresh-contents) (package-install 'use-package)) #+END_SRC ** Generic packages Here I install some packages that don't need configuration. Remember to run M-x all-the-icons-install-fonts after the first init to install the fonts. #+BEGIN_SRC elisp (use-package markdown-mode :defer 1 :ensure t :init(add-hook 'markdown-mode-hook 'auto-fill-mode)) (use-package all-the-icons :defer 1 :ensure t) (use-package which-key :ensure t :init (which-key-mode)) #+END_SRC * Autoindentation C-c n for indent-buffer. I don't use the rest. #+BEGIN_SRC emacs-lisp (setq-default tab-width 5) (defvaralias 'sgml-basic-offset 'tab-width) (add-hook 'html-mode-hook (lambda () (set-fill-column 100))) (defun indent-buffer () (interactive) (save-excursion (indent-region (point-min) (point-max) nil))) (global-set-key (kbd "C-c n") 'indent-buffer) ;; C bullshit (c-set-offset 'arglist-cont-nonempty '+) #+END_SRC * Shorcuts Probably this overwrites another keybinding. But since I overwrited it. I don't think i'd ever use the overwritten. #+BEGIN_SRC emacs-lisp (global-set-key (kbd "M-m") 'mark-whole-buffer) (global-set-key (kbd "C-c m") 'man) (define-key org-mode-map (kbd "C-c p") 'org-publish-current-file) (set-frame-font "Hack 17") #+END_SRC * No idea #+BEGIN_SRC emacs-lisp (setq package-enable-at-startup nil) (package-initialize) (setq make-backup-files nil) ; stop creating backup~ files (setq auto-save-default nil) ; stop creating #autosave# files (put 'upcase-region 'disabled nil) (defun contextual-menubar (&optional frame) "Display the menubar in FRAME (default: selected frame) if on a graphical display, but hide it if in terminal." (interactive) (set-frame-parameter frame 'menu-bar-lines (if (display-graphic-p frame) 1 0))) (add-hook 'after-make-frame-functions 'contextual-menubar) (use-package zencoding-mode :ensure t :defer 1) #+END_SRC * My functions Functions I wrote because emacs lisp is cool and useful. #+begin_src emacs-lisp (defun sosa/goto-previous-buffer () "Switch to the previous buffer." (interactive) (switch-to-buffer (other-buffer))) (defun sosa/kill-inner-word () "Unlike (kill-word) function, this function actually kill a world." (interactive) (forward-char 1) (backward-word) (kill-word 1)) (defun sosa/no-lines() "Locally disable number line mode, useful hooks." (display-line-numbers-mode -1)) (defun sosa/git-pushall () "Call the git pushall shell command." (interactive) (shell-command "git pushall")) (defun sosa/goto-dashboard () "Goes to the dashboard buffer" (interactive) (switch-to-buffer "*dashboard*") (dashboard-mode) (dashboard-refresh-buffer)) (setq org-publish-project-alist '(("suragu.net" :base-directory "~/docs/qorg_qorg/" :publishing-directory "~/docs/mounts/sites/suragu.net" :section-numbers nil :publishing-function org-html-publish-to-html :table-of-contents nil :recursive t ))) (defun sosa/make-website () (interactive) (org-publish "suragu.net")) (defun run-current-file () "Execute or compile the current file. For example, if the current buffer is the file x.pl, then it'll call “perl x.pl” in a shell. The file can be php, perl, python, bash, java. File suffix is used to determine what program to run." (interactive) (let (ext-map file-name file-ext prog-name cmd-str) ; get the file name ; get the program name ; run it (setq ext-map '( ("php" . "php") ("pl" . "perl") ("py" . "python") ("p6" . "raku") ("raku" . "raku") ("sh" . "bash") ("java" . "javac") ) ) (setq file-name (buffer-file-name)) (setq file-ext (file-name-extension file-name)) (setq prog-name (cdr (assoc file-ext ext-map))) (setq cmd-str (concat prog-name " " file-name)) (shell-command cmd-str))) #+end_src * Programs Emacs customization, Here is where most of the configuration is. ** Pseudopersonalization Sane defaults!!! #+BEGIN_SRC emacs-lisp (tool-bar-mode -1) (menu-bar-mode -1) (scroll-bar-mode -1) (global-hl-line-mode) (set-face-background hl-line-face "#434343") (setq-default cursor-type 'box) (blink-cursor-mode 1) (setq-default major-mode 'text-mode) (defalias 'yes-or-no-p 'y-or-n-p) ;; Are you experienced? (set-face-background 'line-number nil) (set-face-background 'line-number-current-line nil) (setq-default Man-notify-method 'pushy) #+END_SRC ** Highlight matching parentheses Useful for programming in lisp. I don't program in Lisp, but well. #+BEGIN_SRC emacs-lisp (show-paren-mode 1) (setq show-paren-style 'mixed) (setq startup/gc-cons-threshold gc-cons-threshold) (setq gc-cons-threshold most-positive-fixnum) (defun startup/reset-gc () (setq gc-cons-threshold startup/gc-cons-threshold)) (add-hook 'emacs-startup-hook 'startup/reset-gc) #+END_SRC ** Tramp mode shit (basically) no limit for remote files. #+begin_src emacs-lisp (set-variable 'tramp-copy-size-limit 122222222222) (set-variable 'tramp-inline-compress-start-size 12222222222222) #+end_src ** Lines and columns Show relative lines in each file. Also display the column in the minibuffer. #+BEGIN_SRC emacs-lisp (global-display-line-numbers-mode 1) (setq display-line-numbers-type 'relative) (column-number-mode 1) #+END_SRC ** Flycheck Flycheck is a syntax validator and lintern for programming. #+BEGIN_SRC emacs-lisp (use-package flycheck :ensure t :init (add-hook 'after-init-hook #'global-flycheck-mode)) #+END_SRC And for raku #+BEGIN_SRC emacs-lisp (use-package flycheck-raku :ensure t :init (add-hook 'raku-mode 'flycheck-raku-mode)) #+END_SRC ** Terminal vterm is better than ansi-term and shit, despite it's kinda slow, it's a price i'm willing to pay. Remember that to compile VTerm you need =cmake= installed. See the error buffer that is created everytime you try to copmile vterm for further information. It should use your default shell by default. #+BEGIN_SRC emacs-lisp (use-package "vterm" :ensure t :bind("C-x C-t" . vterm)) #+END_SRC ** Theme #+begin_src emacs-lisp (load-theme 'misterioso t) (set-cursor-color "cyan") #+end_src ** ctrlf So, you know, C-s in emacs sucks, so this is a repleacement for that. #+BEGIN_SRC emacs-lisp (use-package ctrlf :ensure t :defer 1 :init (ctrlf-mode +1)) #+END_SRC ** Company and Irony Some shit for autocompletion and that kind of shit. #+BEGIN_SRC emacs-lisp (use-package company :defer 1 :ensure t :config (setq company-idle-delay 0) (setq company-minimum-prefix-length 1) (global-company-mode)) (with-eval-after-load 'company (define-key company-active-map (kbd "M-n") nil) (define-key company-active-map (kbd "M-p") nil) (define-key company-active-map (kbd "C-n") #'company-select-next) (define-key company-active-map (kbd "C-p") #'company-select-previous)) #+END_SRC ** Programming language things *** Lisp Parentheses highlight in lisp modes. So you can easily identify them. #+BEGIN_SRC emacs-lisp (use-package rainbow-delimiters :ensure t :init (add-hook 'emacs-lisp-mode-hook 'rainbow-delimiters-mode) (add-hook 'lisp-mode-hook 'rainbow-delimiters-mode) (add-hook 'scheme-mode-hook 'rainbow-delimiters-mode)) (setq lisp-indent-offset 5) #+END_SRC *** Perl I use LSP for perl. #+BEGIN_SRC emacs-lisp (setq perl-indent-level 5) (defalias 'perl-mode 'cperl-mode) (add-hook 'perl-mode-hook (lambda () (lsp) (irony-mode -1))) #+END_SRC *** C* This use c-eldoc mode so it prints the function's prototype in the minibuffer. Which is very useful since Irony works when it wants to. LSP is also used for further Programming. #+BEGIN_SRC emacs-lisp (use-package c-eldoc :ensure t :init (add-hook 'c-mode-hook 'c-turn-on-eldoc-mode)) (setq c-default-style "k&r") (add-hook 'c-mode-hook (lambda () (lsp) (irony-mode -1))) #+END_SRC *** Raku Raku, the cornerstone of any well designed programming language. #+begin_src emacs-lisp (setq raku-indent-offset 5) (setq raku-exec-path "/usr/bin/raku") #+end_src *** HTML & CSS offset #+begin_src emacs-lisp (setq css-indent-offset 5) (setq sgml-basic-offset 5) #+end_src *** org #+begin_src emacs-lisp (setq org-ellipsis " ") (setq org-src-fontify-natively t) (setq org-src-tab-acts-natively t) (setq org-confirm-babel-evaluate nil) (setq org-export-with-smart-quotes t) (setq org-src-window-setup 'current-window) (add-hook 'org-mode-hook 'org-indent-mode) (add-hook 'org-mode-hook 'qorg/no-lines) ;; Syntax highlighting in exports (use-package htmlize :ensure t) (setq org-html-head "" org-html-head-extra "" org-html-head-include-default-style nil org-html-head-include-scripts nil org-html-preamble nil org-html-postamble nil org-html-use-infojs nil) #+end_src ** Keybindings Here I put functions I won't bother to document because they're so simple. #+BEGIN_SRC emacs-lisp (global-set-key (kbd "M-d") 'sosa/kill-inner-word) (global-set-key (kbd "M-.") 'repeat) (global-set-key (kbd "C-x k") 'kill-buffer) (global-set-key (kbd "C-x C-k") 'kill-current-buffer) (global-unset-key (kbd "C-x C-b")) (global-set-key (kbd "C-x C-b") 'sosa/goto-previous-buffer) #+END_SRC ** Hunspell For some reason, there is no ispell spanish in void linux. so i had to fallback to hunspell. which does the same. #+BEGIN_SRC emacs-lisp (defvar ispell-program-name "hunspell") ;; Or whatever you use ;; (ispell, aspell...) #+END_SRC ** Dired Ahhh, the emacs file browser, better than ranger and others... Hide dotfiles: #+BEGIN_SRC emacs-lisp (use-package dired-hide-dotfiles :ensure t :init (defun my-dired-mode-hook () "My `dired' mode hook." ;; To hide dot-files by default (dired-hide-dotfiles-mode) ;; To toggle hiding (define-key dired-mode-map "." #'dired-hide-dotfiles-mode)) (add-hook 'dired-mode-hook #'my-dired-mode-hook)) (use-package async :ensure t :init (dired-async-mode 1)) (add-hook 'dired-mode-hook (lambda () (dired-hide-details-mode))) #+END_SRC Now let's make the thing lysergic #+begin_src emacs-lisp (set-face-foreground dired-directory-face "orange") (set-face-foreground dired-symlink-face "cyan") (set-face-foreground dired-mark-face "green") (set-face-foreground dired-marked-face "blue") #+end_src ** kill ring popup #+BEGIN_SRC emacs-lisp (use-package popup-kill-ring :ensure t :bind ("M-y" . popup-kill-ring)) #+END_SRC ** scrolling Scroll by lines rather than by pages. #+begin_src emacs-lisp (setq scroll-step 1) (setq scroll-conservatively 10000) (setq auto-window-vscroll nil) (scroll-bar-mode 1) #+end_src ** Shell #+begin_src emacs-lisp (add-hook 'shell-mode-hook 'yas-minor-mode) (add-hook 'shell-mode-hook 'flycheck-mode) (add-hook 'shell-mode-hook 'company-mode) (defun shell-mode-company-init () (setq-local company-backends '((company-shell company-shell-env company-etags company-dabbrev-code)))) (use-package company-shell :ensure t :config (require 'company) (add-hook 'shell-mode-hook 'shell-mode-company-init)) #+end_src ** Mark multiple Multiple cursors :DD #+begin_src emacs-lisp (use-package "multiple-cursors" :ensure t :bind ("C-c q" . 'mc/mark-next-like-this)) #+end_src ** Highlight indent guides I don't really know, it looks cool. #+begin_src emacs-lisp (use-package "highlight-indent-guides" :ensure t :defer :init (add-hook 'prog-mode-hook 'highlight-indent-guides-mode) (setq highlight-indent-guides-method 'bitmap)) #+end_src ** Ace jump mode Run, live to fly Fly to live, do or die Won't you run, live to fly Fly to live, aces high #+begin_src emacs-lisp (use-package "ace-jump-mode" :ensure t :bind("C-l" . 'ace-jump-mode)) #+end_src And same but jumping between frames #+begin_src emacs-lisp (use-package "ace-window" :ensure t :bind("M-l" . 'ace-window) :bind("M-o" . 'ace-delete-window)) ;; Gotta remove the bad habits (global-unset-key (kbd "C-x o")) #+end_src ** Expand region #+begin_src emacs-lisp (use-package expand-region :ensure t :init(global-unset-key (kbd "C-q")) (global-set-key (kbd"C-q") 'er/expand-region)) (defun sosa/mark-words-between-quotes () "Does that." (interactive) (er/expand-region 2)) (global-set-key (kbd "C-c q") 'qorg/mark-words-between-quotes) #+end_src ** Beacon mode #+begin_src emacs-lisp (use-package "beacon" :ensure t :init(beacon-mode 1)) #+end_src ** LSP Le language server #+begin_src emacs-lisp (use-package "lsp-mode" :ensure t ) (use-package "lsp-ui" :ensure t :init(add-hook 'lsp-mode-hook 'lsp-ui-mode)) #+end_src ** Hooks I am tired of =M-x auto-fill-mode= in some modes #+begin_src emacs-lisp (add-hook 'org-mode-hook 'auto-fill-mode) (add-hook 'text-mode-hook 'auto-fill-mode) (add-hook 'sgml-mode-hook 'auto-fill-mode) (add-hook 'sgml-mode-hook 'zencoding-mode) (add-hook 'Man-mode-hook 'qorg/no-lines) (add-hook 'speedbar-mode-hook 'qorg/no-lines) #+end_src ** Hungry delete Having to delete multiple whitespaces is one of the things I hate, thankfully there's this thing. #+begin_src emacs-lisp (use-package "hungry-delete" :ensure t :init(global-hungry-delete-mode)) #+end_src ** Yasnippet #+begin_src emacs-lisp (use-package "yasnippet" :ensure t :config (use-package "yasnippet-snippets" :ensure t) :init(yas-global-mode) (yas-reload-all)) #+end_src ** Org-mode customization #+begin_src emacs-lisp (use-package "org-bullets" :ensure t :config (add-hook 'org-mode-hook 'org-bullets-mode)) (local-unset-key (kbd"C-c C-q")) (set-face-font 'org-level-1 "IBM Plex Mono 16") (set-face-font 'org-level-2 "IBM Plex Mono 15") (set-face-font 'org-level-3 "IBM Plex Mono 14") #+end_src ** zzz-to-char It's like ace-whatever but for zapping characters. =zap-to-char= #+begin_src emacs-lisp (use-package zzz-to-char :ensure t :bind("M-z" . 'zzz-up-to-char)) #+end_src ** Helpful Better \*help\* buffer #+begin_src emacs-lisp (use-package helpful :ensure t :bind ("C-h f". #'helpful-callable) :bind ("C-h v". #'helpful-variable) :bind ("C-h k". #'helpful-key)) #+end_src ** Treemacs Sidebar xdxd #+begin_src emacs-lisp (use-package treemacs :ensure t :defer t :init (with-eval-after-load 'winum (define-key winum-keymap (kbd "M-0") #'treemacs-select-window)) :config (progn (setq treemacs-collapse-dirs (if treemacs-python-executable 3 0) treemacs-deferred-git-apply-delay 0.5 treemacs-directory-name-transformer #'identity treemacs-display-in-side-window t treemacs-eldoc-display 'simple treemacs-file-event-delay 5000 treemacs-file-extension-regex treemacs-last-period-regex-value treemacs-file-follow-delay 0.2 treemacs-file-name-transformer #'identity treemacs-follow-after-init t treemacs-expand-after-init t treemacs-find-workspace-method 'find-for-file-or-pick-first treemacs-git-command-pipe "" treemacs-goto-tag-strategy 'refetch-index treemacs-indentation 2 treemacs-indentation-string " " treemacs-is-never-other-window nil treemacs-max-git-entries 5000 treemacs-missing-project-action 'ask treemacs-move-forward-on-expand nil treemacs-no-png-images nil treemacs-no-delete-other-windows t treemacs-project-follow-cleanup nil treemacs-persist-file (expand-file-name ".cache/treemacs-persist" user-emacs-directory) treemacs-position 'left treemacs-read-string-input 'from-child-frame treemacs-recenter-distance 0.1 treemacs-recenter-after-file-follow nil treemacs-recenter-after-tag-follow nil treemacs-recenter-after-project-jump 'always treemacs-recenter-after-project-expand 'on-distance treemacs-litter-directories '("/node_modules" "/.venv" "/.cask") treemacs-show-cursor nil treemacs-show-hidden-files t treemacs-silent-filewatch nil treemacs-silent-refresh nil treemacs-sorting 'alphabetic-asc treemacs-select-when-already-in-treemacs 'move-back treemacs-space-between-root-nodes t treemacs-tag-follow-cleanup t treemacs-tag-follow-delay 1.5 treemacs-text-scale nil treemacs-user-mode-line-format nil treemacs-user-header-line-format nil treemacs-wide-toggle-width 70 treemacs-width 25 treemacs-width-increment 1 treemacs-width-is-initially-locked t treemacs-workspace-switch-cleanup nil) ;; The default width and height of the icons is 22 pixels. If you are ;; using a Hi-DPI display, uncomment this to double the icon size. ;;(treemacs-resize-icons 44) (treemacs-follow-mode t) (treemacs-filewatch-mode t) (treemacs-fringe-indicator-mode 'always) (pcase (cons (not (null (executable-find "git"))) (not (null treemacs-python-executable))) (`(t . t) (treemacs-git-mode 'deferred)) (`(t . _) (treemacs-git-mode 'simple))) (treemacs-hide-gitignored-files-mode nil)) :bind (:map global-map ("M-0" . treemacs-select-window) ("C-x t 1" . treemacs-delete-other-windows) ("C-x t t" . treemacs) ("C-x t d" . treemacs-select-directory) ("C-x t B" . treemacs-bookmark) ("C-x t C-t" . treemacs-find-file) ("C-x t M-t" . treemacs-find-tag))) (use-package treemacs-projectile :after (treemacs projectile) :ensure t) (use-package treemacs-icons-dired :hook (dired-mode . treemacs-icons-dired-enable-once) :ensure t) (use-package treemacs-tab-bar ;;treemacs-tab-bar if you use tab-bar-mode :after (treemacs) :ensure t :config (treemacs-set-scope-type 'Tabs)) #+end_src ** Projectile Projectile is a project manager which helps you with git and stuff. #+begin_src emacs-lisp (use-package projectile :ensure t :init(projectile-mode)) #+end_src ** Nyancat Yes. #+begin_src emacs-lisp (use-package nyan-mode :ensure t :init(nyan-mode)) #+end_src * Vertico Better interactive selection minibuffer. Alternative to ido and helm. #+begin_src emacs-lisp (use-package vertico :ensure t :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], 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)) #+end_src * CRUX This thing add sane shortcuts for emacs #+begin_src emacs-lisp (use-package "crux" :ensure t :bind("C-k" . 'crux-smart-kill-line) :bind("C-c o" . 'crux-open-with) :bind("C-c D" . 'crux-delete-buffer-and-file) :bind("C-x C-r" . 'crux-reopen-as-root) :bind("C-x C-d" . 'crux-duplicate-current-line-or-region) :bind("C-c u" . 'crux-view-url) :bind("C-c s" . 'crux-create-scratch-buffer)) #+end_src * Dashboard The dashboard is a good index for your things. So it's useful to have it Here is an useful function I wrote so you can go to the dashboard (Or create it in case you accidentally killed the buffer) #+begin_src emacs-lisp (global-set-key (kbd "C-c C-d") 'sosa/goto-dashboard) #+end_src #+BEGIN_SRC emacs-lisp (use-package dashboard :ensure t :init (dashboard-setup-startup-hook) (setq dashboard-items '( (recents . 7) (bookmarks . 7) )) (setq dashboard-startup-banner 'logo) (setq dashboard-banner-logo-title "Welcome to Editor MACroS") (setq dashboard-startup-banner "~/.emacs.d/img/banner.png") (setq dashboard-set-heading-icons t) (setq dashboard-set-file-icons t)) #+END_SRC * Modeline #+begin_src emacs-lisp (use-package "doom-modeline" :ensure t :init(doom-modeline-mode) :config (setq doom-modeline-height 25) (setq doom-modeline-hud nil) (setq doom-modeline-icon t) (setq doom-modeline-major-mode-icon nil) (setq doom-modeline-time-icon nil) (setq doom-modeline-env-version t) (setq doom-modeline-env-python-executable "python") (setq doom-modeline-env-perl-executable "perl") ) #+end_src