some more work on emacs init.el

This commit is contained in:
Geir Okkenhaug Jerstad 2025-05-28 09:48:23 +02:00
parent 7dd753506f
commit a5d571fc75
2 changed files with 625 additions and 21 deletions

View file

@ -7,7 +7,15 @@
* About * About
My attempt at a litterate configuration for Emacs. My attempt at a litterate configuration for Emacs.
to tangle this file, run the following command in Emacs:
#+BEGIN_SRC emacs-lisp
(org-babel-tangle)
#+END_SRC
or keyboard shortcut `C-c C-v t` (org-babel-tangle) in Emacs.
This will generate the `~/.emacs.d/init.el` file with the configuration.
* Prep * Prep
** Copilot Authentication ** Copilot Authentication
To use GitHub Copilot, you need to authenticate with your GitHub account. This is done by running the following command in Emacs: To use GitHub Copilot, you need to authenticate with your GitHub account. This is done by running the following command in Emacs:
after installing the copilot package: after installing the copilot package:
@ -19,6 +27,29 @@ Try to trigger the GitHub OAuth flow from within Emacs:
* Configuration * Configuration
** Setup lexical binding
Here we set up lexical binding, which is a feature in Emacs Lisp that allows for more efficient variable scoping and function closures. This is recommended for performance reasons.
#+BEGIN_SRC emacs-lisp
;; enable lexical binding
(setq lexical-binding t)
#+END_SRC
** Set automatic update of packages
We set up Emacs to automatically update packages on startup. This ensures that we always have the latest versions of the packages we use.
#+BEGIN_SRC emacs-lisp
(defun geokkjer/display-startup-time ()
(message "Emacs loaded in %s with %d grabage collections."
(format "%.2f seconds"
(float-time
(time-subtract after-init-time before-init-time)))
gcs-done))
(add-hook 'emacs-startup-hook #'geokkjer/display-startup-time)
(setq gc-cons-threshold (* 50 1000 1000))
#+END_SRC
** Customize UI ** Customize UI
Here we set up the UI to our liking. We disable the menu bar, tool bar, and scroll bar, and set the font size to 14pt. Here we set up the UI to our liking. We disable the menu bar, tool bar, and scroll bar, and set the font size to 14pt.
#+BEGIN_SRC emacs-lisp #+BEGIN_SRC emacs-lisp
@ -67,6 +98,30 @@ Set up doom modeline, which is a nice status line for Emacs. We set it up to sho
(setq use-package-always-ensure t) (setq use-package-always-ensure t)
#+END_SRC #+END_SRC
** Org Mode
Configure Org-mode for literate programming and note-taking.
#+BEGIN_SRC emacs-lisp
;; ensure org-mode is installed and up to date
(use-package org
:ensure t
:mode ("\\.org\\'" . org-mode)
:config
;; enable syntax highlighting in code blocks
(setq org-src-fontify-natively t)
;; preserve indentation in code blocks
(setq org-src-preserve-indentation t)
;; enable babel for code execution
(org-babel-do-load-languages
'org-babel-load-languages
'((emacs-lisp . t)
(shell . t)
(python . t)
(nix . t)))
;; don't ask for confirmation when evaluating code blocks
(setq org-confirm-babel-evaluate nil))
#+END_SRC
* Code Completion and ide features * Code Completion and ide features
** LSP Mode ** LSP Mode
Here we install lsp-mode and lsp-ui, which are the core components of the LSP (Language Server Protocol) support in Emacs. We also set up keybindings for common LSP commands. Here we install lsp-mode and lsp-ui, which are the core components of the LSP (Language Server Protocol) support in Emacs. We also set up keybindings for common LSP commands.
@ -105,27 +160,7 @@ Here we install from MELPA, enable it in all prog-modes and bind keys for comple
** Language support ** Language support
Here we install and configure support for various programming languages. We use the `use-package` macro to ensure that the packages are installed and configured correctly. Here we install and configure support for various programming languages. We use the `use-package` macro to ensure that the packages are installed and configured correctly.
#+BEGIN_SRC emacs-lisp
;; install and configure javscript-mode
(use-package javscript-mode
:ensure t
:mode "\\.js\\'")
;; lsp support for javascript
(use-package lsp-javascript
:ensure t
:mode "\\.js\\'")
;; install and configure gleam-mode
(use-package gleam-mode
:ensure t
:mode "\\.gleam\\'")
#+END_SRC
;; lsp support for gleam
(use-package lsp-gleam
:ensure t
:mode "\\.gleam\\'")
#+END_SRC
** NixOS from Emacs ** NixOS from Emacs
Editing Nix files and doing NixOS admin stuff like nixos-rebuild boot --upgrade Editing Nix files and doing NixOS admin stuff like nixos-rebuild boot --upgrade

569
init.el Normal file
View file

@ -0,0 +1,569 @@
;;; -*- lexical-binding: t -*-
(defun geokkjer/display-startup-time ()
(message "Emacs loaded in %s with %d grabage collections."
(format "%.2f seconds"
(float-time
(time-subtract after-init-time before-init-time)))
gcs-done))
(add-hook 'emacs-startup-hook #'geokkjer/display-startup-time)
(setq gc-cons-threshold (* 50 1000 1000))
;; Initialize package sources
(require 'package)
;; Set the repos
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
("org" . "https://orgmode.org/elpa/")
("nongnu" . "https://elpa.nongnu.org/nongnu/")
("elpa" . "https://elpa.gnu.org/packages/")))
(package-initialize)
(unless package-archive-contents
(package-refresh-contents))
;; Initialize use-package in case we are on non-Linux platform
(unless (package-installed-p 'use-package)
(package-install 'use-package))
(require 'use-package)
(setq use-package-always-ensure t)
(use-package auto-package-update
:custom
(auto-package-update-interval 7)
(auto-package-update-prompt-before-update t)
(auto-package-update-hide-results t)
:config
(auto-package-update-maybe)
(auto-package-update-at-time "09:00"))
;; Turns off the startup-message
(setq inhibit-startup-message t)
;; Disable UI-elements
(scroll-bar-mode -1) ; Disable visible scrollbar
(tool-bar-mode -1) ; Disable the toolbar
(tooltip-mode -1) ; Disable tooltips
(set-fringe-mode 10) ; Give us some breathing room
(menu-bar-mode -1) ; Disable the menu bar
;; Set up the visual bell
(setq visible-bell t)
;; Setting to auto reload files
(setq auto-revert-mode t)
;; Doom modline, all-the-icons and doom-theme
(use-package doom-modeline
:ensure t
:init (doom-modeline-mode 1)
:custom ((doom-modeline-height 15)))
(setq doom-modeline-icon t)
(use-package all-the-icons)
(use-package doom-themes
:init (load-theme 'doom-monokai-pro t))
;; Enable line numbers
(column-number-mode)
(global-display-line-numbers-mode t)
;; Disable line numbers for some modes
(dolist (mode '(org-mode-hook
geiser-mode-hook
term-mode-hook
shell-mode-hook
vterm-mode-hook
eshell-mode-hook))
(add-hook mode (lambda () (display-line-numbers-mode 0))))
(use-package spacious-padding
:ensure t
:hook (after-init . spacious-padding-mode))
(defvar geokkjer/default-font-size 140)
(set-face-attribute 'default nil :font "Fira Code Nerd Font Mono" :height geokkjer/default-font-size)
;; Set the fixed pitch face
(set-face-attribute 'fixed-pitch nil :font "Fira Code Nerd Font Mono" :height 140)
;; Set the variable pitch face
(set-face-attribute 'variable-pitch nil :font "Fira Code Nerd Font" :height 130 :weight 'regular)
(use-package swiper)
(use-package ivy
:diminish
:bind (("C-s" . swiper)
:map ivy-minibuffer-map
("TAB" . ivy-alt-done)
("C-l" . ivy-alt-done)
("C-j" . ivy-next-line)
("C-k" . ivy-previous-line)
:map ivy-switch-buffer-map
("C-k" . ivy-previous-line)
("C-l" . ivy-done)
("C-d" . ivy-reverse-buffer-kill)
:map ivy-reverse-i-search-map
("C-k" . ivy-previous-line)
("C-d" . ivy-reversee-i-search-kill))
:config
(ivy-mode 1))
(use-package ivy-rich
:after ivy
:init
(ivy-rich-mode 1))
(use-package ivy-posframe
:after ivy
:init
(ivy-posframe-mode 1))
(use-package counsel
:bind (("M-x" . counsel-M-x)
("C-x b" . counsel-ibuffer)
("C-x C-f" . counsel-find-file)
:map minibuffer-local-map
("C-r" .'counsel-minibuffer-history))
:config
(setq ivy-initial-inputs-alist nil)
(counsel-mode 1))
(use-package which-key
:defer 0
:diminish which-key-mode
:config
(which-key-mode)
(setq which-key-idle-delay 1))
(defun efs/org-mode-setup ()
(org-indent-mode)
(variable-pitch-mode 1)
(visual-line-mode 1))
;; Org Mode Configuration
(defun efs/org-font-setup ()
;; Replace list hyphen with dot
(font-lock-add-keywords 'org-mode
'(("^ *\\([-]\\) "
(0 (prog1 () (compose-region
(match-beginning1)
(match-end 1)
"")))))))
;; Show overview when open
(setq org-startup-folded t)
;; Set faces for heading levels
(with-eval-after-load 'org-faces
(dolist (face '((org-level-1 . 1.2)
(org-level-2 . 1.1)
(org-level-3 . 1.05)
(org-level-4 . 1.0)
(org-level-5 . 1.1)
(org-level-6 . 1.1)
(org-level-7 . 1.1)
(org-level-8 . 1.1)))
(set-face-attribute (car face) nil :font "Fira Code Nerd Font" :weight 'regular
:height (cdr face))
;; Ensure that anything that should be fixed-pitch in Org files appears that way
(set-face-attribute 'org-block nil :foreground nil :inherit 'fixed-pitch)
(set-face-attribute 'org-code nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-table nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-verbatim nil :inherit '(shadow fixed-pitch))
(set-face-attribute 'org-special-keyword nil :inherit
'(font-lock-comment-face fixed-pitch))
(set-face-attribute 'org-meta-line nil :inherit '(font-lock-comment-face
fixed-pitch))
(set-face-attribute 'org-checkbox nil :inherit 'fixed-pitch)))
(use-package org
:pin org
:commands (org-capture org-agenda)
:hook (org-mode . efs/org-mode-setup)
:config
(setq org-ellipsis "")
(use-package org-bullets
:hook (org-mode . org-bullets-mode)
:custom
(org-bullets-bullet-list '("" "" "" "" "" "" "")))
(defun efs/org-mode-visual-fill ()
(setq visual-fill-column-width 100
visual-fill-column-center-text t)
(visual-fill-column-mode 1))
(use-package visual-fill-column
:hook (org-mode . efs/org-mode-visual-fill)))
(with-eval-after-load 'org
(org-babel-do-load-languages
'org-babel-load-languages
'((lisp . t)
(scheme . t)
(emacs-lisp . t)
(shell . t)
(python . t)))
(push '("conf-unix" . conf-unix) org-src-lang-modes))
(setq org-confirm-babel-evaluate nil)
;; This is needed as of Org 9.2
(with-eval-after-load 'org
(require 'org-tempo)
(add-to-list 'org-structure-template-alist '("sh" . "src shell"))
(add-to-list 'org-structure-template-alist '("el" . "src emacs-lisp"))
(add-to-list 'org-structure-template-alist '("py" . "src python"))
(add-to-list 'org-structure-template-alist '("go" . "src go"))
(add-to-list 'org-structure-template-alist '("sc" . "src scheme"))
(add-to-list 'org-structure-template-alist '("li" . "src lisp"))
(add-to-list 'org-structure-template-alist '("ru" . "src rust"))
(add-to-list 'org-structure-template-alist '("nx" . "src nix")))
(setq org-src-tab-acts-natively t)
(use-package lorem-ipsum
:after org)
(use-package treemacs
:ensure t
:bind ("<f5>" . treemacs)
:custom (treemacs-is-never-other-window t)
:hook (treemacs-mode . treemacs-project-follow-mode))
(defun geokkjer/lsp-mode-setup ()
(setq lsp-headerline-breadcrumb-segments '(path-up-to-project file symbols))
(lsp-headerline-breadcrumb-mode))
(use-package lsp-mode
:commands (lsp lsp-deferred)
:hook ((lsp-mode . geokkjer/lsp-mode-setup)
(lsp-mode . lsp-enable-which-key-integration)
:init
(setq lsp-keymap-prefix "C-c l")))
;; (use-package lsp-org
;; :after lsp)
(use-package lsp-ivy
:after lsp)
(use-package lsp-ui
:hook (lsp-mode . lsp-ui-mode)
:custom
(lsp-ui-doc-psition 'bottom))
(setq lsp-ui-sidline-enable nil)
(setq lsp-ui-sideline-show-hover nil)
(use-package lsp-treemacs
:after lsp)
(use-package ccls
:defer t
:hook ((c-mode c++-mode objc-mode) .
(lambda () (require 'ccls) (lsp)))
:custom
(ccls-executable (executable-find "ccls")) ; Add ccls to path if you haven't done so
(ccls-sem-highlight-method 'font-lock)
(ccls-enable-skipped-ranges nil)
:config
(lsp-register-client
(make-lsp-client
:new-connection (lsp-tramp-connection (cons ccls-executable ccls-args))
:major-modes '(c-mode c++-mode cuda-mode objc-mode)
:server-id 'ccls-remote
:multi-root nil
:remote? t
:notification-handlers
(lsp-ht ("$ccls/publishSkippedRanges" #'ccls--publish-skipped-ranges)
("$ccls/publishSemanticHighlight" #'ccls--publish-semantic-highlight))
:initialization-options (lambda () ccls-initialization-options)
:library-folders-fn nil)))
;; C sharp
(use-package csharp-mode
:hook (csharp-mode . (lambda ()
(require 'csharp-ls)
(lsp)))
:mode "\\.cs\\'")
;; Zig
(use-package zig-mode
:ensure t
:hook (zig-mode . (lambda ()
(require 'zls
(lsp-deferred))
(prettify-symbols-mode)))
:mode "\\.zig\\'")
(use-package geiser-racket
:ensure t)
(use-package geiser-guile
:ensure t)
(use-package lsp-scheme)
(require 'lsp-scheme)
(add-hook 'scheme-mode-hook #'lsp-scheme-guile)
(setq lsp-scheme-implementation "guile")
(use-package go-mode
:ensure t
:hook (go-mode . (lambda ()
(require 'golsp
(lsp-deferred))
(prettify-symbols-mode)))
:mode "\\.go\\'")
(use-package flycheck-gometalinter
:ensure t
:config
(progn
(flycheck-gometalinter-setup)))
(use-package web-mode
:mode "\\.html\\'"
:hook (web-mode . lsp-deferred)
:config
(add-to-list 'auto-mode-alist '("\\.html?\\'" . web-mode))
(setq web-mode-engines-alist '(("django" . "\\.html\\'"))))
;; Simple-httpd webserver to preview webpages
(use-package simple-httpd
:ensure t)
(use-package python-mode
:ensure nil
:hook (python-mode . lsp-deferred)
:custom
(python-shell-interpreter "python3")
:mode "\\.py\\'"
:config
)
(use-package pyvenv
:after python-mode
:config
(pyvenv-mode 1))
(use-package lsp-python-ms
:ensure t
:hook (python-mode . (lambda ()
(require 'lsp-python-ms)
(lsp-deferred)))
:init
(setq lsp-python-ms-executable (executable-find "python-language-server")))
;; Javascript
(use-package js2-mode
:hook (js2-mode . (lambda ()
(require 'ts-ls
(lsp-deferred))))
:mode "\\.js\\'")
(use-package rust-mode
:ensure nil
:hook (rust-mode . (lambda ()
(require 'lsp-rust-server
(lsp-deferred))
(prettify-symbols-mode)))
:mode "\\.rs\\'")
(setq rust-format-on-save t)
(use-package flycheck-rust)
(with-eval-after-load 'rust-mode
(add-hook 'flycheck-mode-hook #'flycheck-rust-setup))
(use-package sql-indent)
(use-package nix-mode
:mode "\\.nix\\'")
(add-to-list 'lsp-language-id-configuration '(nix-mode . "nix"))
(lsp-register-client
(make-lsp-client :new-connection (lsp-stdio-connection '("rnix-lsp"))
:major-modes '(nix-mode)
:server-id 'nix))
(use-package kubernetes
:commands kubernetes-overview
:config
(setq kubernetes-poll-frequency 3600
kubernetes-redraw-frequency 3600))
(use-package yaml-mode)
(use-package company
:after lsp-mode
:hook (lsp-mode . company-mode)
:bind (:map company-active-map
("<tab>" . company-complete-section))
(:map lsp-mode-map
("<tab>" . company-indent-or-complete-common))
:custom
(company-minimum-orefix-lenght 1)
(company-idle-delay 0.0))
(use-package company-box
:hook (company-mode . company-box-mode))
;; rainbow-delimiters
(use-package rainbow-delimiters
:hook (prog-mode . rainbow-delimiters-mode))
(use-package flycheck
:ensure t
:init (global-flycheck-mode))
;; TODO learn to use projectile
(use-package projectile
:diminish
:config
:custom ((projectile-completion-system 'ivy))
:bind-keymap
("C-c p" . projectile-command-map)
:init
(when (file-directory-p "~/Projects/Code")
(setq projectile-projects-search-path '("~/Projects/Code")))
(setq projectile-switch-project-action #'projectile-dired))
(use-package counsel-projectile
:after projectile
:config (counsel-projectile-mode))
;; TODO learn git and Magit
(use-package magit
:commands magit-status
:custom
(magit-display-buffer-function
#'magit-display-buffer-same-window-except-diff-v1))
;; TODO config for service
(use-package forge
:after magit)
(use-package helpful
:commands (helpful-callable helpful-variable helpful-command helpful-key)
:custom
(counsel-describe-function-function #'helpful-callable)
(counsel-describe-variable-function #'helpful-variable)
:bind
([remap describe-function] . counsel-describe-function)
([remap describe-command] . helpful-command)
([remap describe-variable] . counsel-describe-variable)
([remap describe-key] . helpful-key))
(use-package general
:config
(general-create-definer geokkjer/leader-keys
:keymaps '(normal insert visual emacs)
:prefix "SPC"
:global-prefix "C-SPC")
(geokkjer/leader-keys
"t" '(:ignore t :which-key "toggles")
"tt" '(counsel-load-theme :which-key "choose theme")))
(use-package term
:commands term
:config
(setq explicit-shell-file-name "bash")
;; (setq explicit-zsh-args '())
(setq term-prompt-regexp "^[^#$%>\n]*[#$%>] *"))
(use-package eterm-256color
:hook (term-mode . eterm-256color-mode))
(use-package vterm
:ensure t
:commands vterm
:config
(setq vterm-shell "zsh")
(setq vterm-max-scrollback 10000))
(defun geokkjer/configure-eshell ()
;; Make eshell svae history when it is open
(add-hook 'eshell-pre-command-hook 'eshell-save-some-history)
;; Truncate buffer for performance
(add-to-list 'eshell-output-filter-functions 'eshell-truncate-buffer)
(setq eshell-history-size 10000
eshell-buffer-maximum-lines 10000
eshell-hist-ignoredups t
eshell-scroll-to-bottom-on-input t))
(use-package eshell-git-prompt
:after eshell)
(use-package eshell
:hook (eshell-first-time-mode . geokkjer/configure-eshell)
:config
(with-eval-after-load 'esh-opt
(setq eshell-destroy-buffer-when-process-dies t)
(setq eshell-visual-commands '("htop" "zsh" "vim" "glances")))
(eshell-git-prompt-use-theme 'powerline))
(use-package dired
:ensure nil
:commands (dired dired-jump)
:bind (("C-x C-j" . dired-jump))
:custom ((dired-listing-switches "-agho --group-directories-first")))
(use-package dired-single
:after dired)
(use-package all-the-icons-dired
:hook (dired-mode . all-the-icons-dired-mode))
(use-package dired-open
:after dired
:config
(setq dired-open-exstensions '(("png" . "feh")
("mkv" . "mpv"))))
(use-package dired-hide-dotfiles
:hook (dired-mode . dired-hide-dotfiles-mode))
;; Make gc pauses faster by decreasing the threshold
(setq gc-cons-threshold (* 2 1000 1000))
(server-start)
(custom-set-variables
;; custom-set-variables was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(package-selected-packages
'(lsp-scheme tree-sitter-indent tree-sitter-langs tree-sitter dired-hide-dotfiles dired-open all-the-icons-dired dired-single eshell-git-prompt vterm eterm-256color general helpful forge magit counsel-projectile projectile rainbow-delimiters company-box company yaml-mode kubernetes nix-mode sql-indent flycheck-rust lsp-python-ms pyvenv simple-httpd web-mode flycheck-gometalinter go-mode geiser-guile geiser-racket zig-mode ccls lsp-treemacs lsp-ui lsp-ivy lsp-mode visual-fill-column org-bullets treemacs lorem-ipsum which-key counsel ivy-posframe ivy-rich swiper use-package spacious-padding doom-themes doom-modeline auto-package-update all-the-icons))
'(warning-suppress-log-types '((comp))))
(custom-set-faces
;; custom-set-faces was added by Custom.
;; If you edit it by hand, you could mess it up, so be careful.
;; Your init file should contain only one such instance.
;; If there is more than one, they won't work right.
'(fringe ((t :background "#282a36")))
'(header-line ((t :box (:line-width 4 :color "#22232d" :style nil))))
'(header-line-highlight ((t :box (:color "#f8f8f2"))))
'(keycast-key ((t)))
'(line-number ((t :background "#282a36")))
'(mode-line ((t :box (:line-width 6 :color "#22232d" :style nil))))
'(mode-line-active ((t :box (:line-width 6 :color "#22232d" :style nil))))
'(mode-line-highlight ((t :box (:color "#f8f8f2"))))
'(mode-line-inactive ((t :box (:line-width 6 :color "#252631" :style nil))))
'(tab-bar-tab ((t :box (:line-width 4 :color "#282a36" :style nil))))
'(tab-bar-tab-inactive ((t :box (:line-width 4 :color "#1E2029" :style nil))))
'(tab-line-tab ((t)))
'(tab-line-tab-active ((t)))
'(tab-line-tab-inactive ((t)))
'(vertical-border ((t :background "#282a36" :foreground "#282a36")))
'(window-divider ((t (:background "#282a36" :foreground "#282a36"))))
'(window-divider-first-pixel ((t (:background "#282a36" :foreground "#282a36"))))
'(window-divider-last-pixel ((t (:background "#282a36" :foreground "#282a36")))))