Skip to content

Latest commit

 

History

History
1502 lines (1019 loc) · 40.9 KB

Init.org

File metadata and controls

1502 lines (1019 loc) · 40.9 KB

Beginning

;;; Init.org --- My Emacs config.
;;; Commentary:
;; My Emacs config inspired by David Wilsons emacs-from-scratch youtube series

;;; Code:

Config

Tangle config on save

(defun org-babel-tangle-config ()
  (when (string-equal  (concat  (file-name-directory  (buffer-file-name)) "emacs/")
                       (expand-file-name user-emacs-directory))
    (let ((org-confirm-babel-evaluate nil))
      (org-babel-tangle))))

(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook #'org-babel-tangle-config)))

Functions

max-line and set-display-line-numbers-width

(defun max-line ()
  "get the max line number of the current buffer"
  (count-lines (point-min) (point-max)))

(defun set-display-line-numbers-width ()
  "get the display-line-number-width so that the width won't resize during scrolling"
  (interactive)
  (setq display-line-numbers-width (string-width (number-to-string (max-line)))))

prefix-with-userprofile and prefix-with-home

(defun prefix-with-userprofile (path)
  "prefix the given path with the path to the userprofile on windows"
  (subst-char-in-string ?\\ ?/ (concat (concat (getenv "userprofile") "/") path)))

(defun prefix-with-home (path)
  "prefix the given path with the path to the home directory of the current user"
  (concat (concat (getenv "HOME" ) "/") path))

(defun prefix-with-userprofile-or-home (path)
  (if (is-windows)
      (prefix-with-userprofile path)
    (prefix-with-home path)))

is-platform

(defun is-windows ()
  "true if system is windows"
  (eq system-type 'windows-nt))

(defun is-linux ()
  "true if system is linux"
  (eq system-type 'gnu/linux))

(defun is-osx ()
  "true if system is mac osx"
  (eq system-type 'darwin))

(defun is-freebsd ()
  "true if system is mac osx"
  (eq system-type 'berkeley-unix))

Reindent-buffer

This funktion reindents the whole buffer and removes trailing whitespaces without moving the cursor

(defun reindent-buffer ()
  "Reindents the whole buffer."
  (interactive)
  (delete-trailing-whitespace)
  (indent-region (point-min) (point-max) nil)
  (untabify (point-min) (point-max)))

(global-set-key [f12] 'reindent-buffer)

My init.el

In Vim you have $MYINITRC set to your config file for easy access, lets to something similar!

(defun myinitorg ()
  "Easy access to the main configuration file."
  (interactive)
  (find-file "~/.emacs.d/Init.org"))

(defun myinitel ()
  "Easy access to the secondary configuration file."
  (interactive)
  (find-file "~/.myinit.el"))

Insert date and time at point

(defun now ()
  "Insert string for the current time formatted."
  (interactive)                 ; permit invocation in minibuffer
  (insert (format-time-string "[%Y-%m-%d %a %H:%M]")))

(defun today ()
  "Insert string for today's date nicely formatted in American style, e.g. Sunday, September 17, 2000."
  (interactive)                 ; permit invocation in minibuffer
  (insert (format-time-string "%A, %B %e, %Y")))

Copy result of eval into kill-ring

(defun my-eval-last-sexp ()
  (interactive)
  (elisp--eval-last-sexp nil)
  (let (result)
    (with-current-buffer (get-buffer " *Echo Area 0*")
      (goto-char (point-min))
      (setq result (read (current-buffer))))
    (kill-new (format "%s" result))))

Global Variables Settings

(defvar *emacsd-directory* user-emacs-directory)
(defvar *conf-directory* "~/.emacs.d/conf")
(defvar *myinitel* ".myinit.el")

(setq user-emacs-directory  "~/.emacs.d/emacs/")

(setq backup-directory-alist '(("." . "~/.emacs-backups"))
      backup-by-copying      t  ; Don't de-link hard links
      version-control        t  ; Use version numbers on backups
      delete-old-versions    nil  ; Automatically delete excess backups:
      kept-new-versions      5  ; how many of the newest versions to keep
      kept-old-versions      5) ; and how many of the old

(defvar temp-directory "~/.emacs-backups/autosave/")
(make-directory temp-directory t)

(setq auto-save-default nil)
(setq auto-save-directory temp-directory
      auto-save-hash-directory (concat temp-directory "/autosave-hash")
      auto-save-directory-fallback "~/emacs-autosave"
      auto-save-list-file-prefix (concat temp-directory "/autosave-")
      auto-save-hash-p nil
      auto-save-timeout 100
      auto-save-interval 300)
(make-directory auto-save-directory t)

(setq create-lockfiles nil)

(setq display-line-numbers-type 'relative)
(global-display-line-numbers-mode)

(setq-default indent-tabs-mode nil)
(setq tab-width 4)
(defvaralias 'c-basic-offset 'tab-width)
(defvaralias 'cperl-indent-level 'tab-width)

(blink-cursor-mode 0)       ; kill it with fire!

;; Make Emacs FUCKING USE SANE ENCODINGS:
(setq locale-coding-system 'utf-8-unix)
(set-default-coding-systems 'utf-8-unix)
(set-terminal-coding-system 'utf-8-unix)
(unless (eq system-type 'windows-nt)

  ;; better scrolling experience
  (setq scroll-margin 0
        scroll-conservatively 10000
        scroll-preserve-screen-position t
        auto-window-vscroll nil)

  ;; on Win32, cooperation between Emacs and other Unicode applications is weird.
  ;; let's avoid that.
  (set-selection-coding-system 'utf-8-unix))

(prefer-coding-system 'utf-8-unix)

(column-number-mode t)

(setq dired-listing-switches "-agho --group-directories-first")

                                        ;(when window-system (set-frame-size (selected-frame) 180 50))

(add-to-list 'default-frame-alist '(height . 50))
(add-to-list 'default-frame-alist '(width . 200))

(set-frame-position (selected-frame) 40 30)

Remove text from **scratch** buffer

(setq initial-scratch-message "")

More realestate by removing scrollbars and toolbars

(scroll-bar-mode -1)        ; Disable visible scrollbar
(tool-bar-mode -1)          ; Disable the toolbar
(tooltip-mode -1)           ; Disable tooltips
(set-fringe-mode 10)        ; Give some breathing room
(menu-bar-mode -1)          ; Disable the menu bar
(show-paren-mode 1)

Blink instead of beep

(setq visible-bell t) ;; kill it with fire also!!!

Better scrolling

;; better scrolling experience
(setq scroll-margin 0)
(setq scroll-conservatively 10000)
(setq scroll-preserve-screen-position t)
(setq auto-window-vscroll nil)

Inhibit startup message

(setq inhibit-startup-message t)

yes-or-no-p

use y and n instead of typing out yes or no

(fset 'yes-or-no-p 'y-or-n-p)
(setq confirm-kill-emacs 'yes-or-no-p)

Font Configuration

I am using the Fira Code and Cantarell fonts for this configuration which will more than likely need to be installed on your machine. Both can usually be found in the various Linux distro package managers.

(defvar efs/default-font-size 110)
(defvar efs/default-variable-font-size 110)

(when (member "Fira Code" (font-family-list))
  (progn
    (set-face-attribute 'default nil :font "Fira Code" :height efs/default-font-size)

    ;; Set the fixed pitch face
    (set-face-attribute 'fixed-pitch nil :font "Fira Code" :height efs/default-font-size)))

(when (member "Cantarell" (font-family-list))
  (progn
    ;; Set the variable pitch face
    (set-face-attribute 'variable-pitch nil :font "Cantarell" :height efs/default-variable-font-size :weight 'regular)))

Aliases

(defalias 'tangle 'org-babel-tangle "tangle the current file")

Compatibility

Freebsd

Fix for Dired

In order for Dired to function properly you need to install the GNU version of ls:

pkg install coreutils

then you need to make sure Emacs can find the binary:

(cond ((eq system-type 'berkeley-unix)
       (setq insert-directory-program "/usr/local/bin/gls")))

Path

(setq exec-path (append exec-path (list (prefix-with-userprofile-or-home ".zvm/bin"))))
(setq exec-path (append exec-path (list (prefix-with-userprofile-or-home "go/bin"))))
(setq exec-path (append exec-path (list "C:/Programs/Elixir/bin")))

Recentf

;(recentf-mode 1)
;(setq recentf-max-menu-items 25)
;(setq recentf-max-saved-items 25)
;(global-set-key "\C-x\ r" 'recentf-open-files)

Packagemanagement

Straight.el

(defvar bootstrap-version)
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 5))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))

(straight-use-package 'use-package)
(setq straight-use-package-by-default t)

Packages

tressit.el

(setq treesit-language-source-alist
      '((bash "https://github.com/tree-sitter/tree-sitter-bash")
        (cmake "https://github.com/uyha/tree-sitter-cmake")
        (css "https://github.com/tree-sitter/tree-sitter-css")
        (elisp "https://github.com/Wilfred/tree-sitter-elisp")
        (go "https://github.com/tree-sitter/tree-sitter-go")
        (gomod "https://github.com/camdencheek/tree-sitter-go-mod")
        (dockerfile "https://github.com/camdencheek/tree-sitter-dockerfile")
        (html "https://github.com/tree-sitter/tree-sitter-html")
        (javascript "https://github.com/tree-sitter/tree-sitter-javascript" "master" "src")
        (json "https://github.com/tree-sitter/tree-sitter-json")
        (make "https://github.com/alemuller/tree-sitter-make")
        (markdown "https://github.com/ikatyang/tree-sitter-markdown")
        (python "https://github.com/tree-sitter/tree-sitter-python")
        (toml "https://github.com/tree-sitter/tree-sitter-toml")
        (tsx "https://github.com/tree-sitter/tree-sitter-typescript" "master" "tsx/src")
        (typescript "https://github.com/tree-sitter/tree-sitter-typescript" "master" "typescript/src")
        (yaml "https://github.com/ikatyang/tree-sitter-yaml")))

Diminish

(use-package diminish)

Completion

(use-package vertico
  :bind (:map vertico-map
              ("C-j" . vertico-next)
              ("C-k" . vertico-previous)
              ("C-f" . vertico-exit)
              :map minibuffer-local-map
              ("M-h" . backward-kill-word))
  :custom
  (vertico-cycle t)
  :init
  (vertico-mode))

(use-package savehist
  :init
  (savehist-mode))

(use-package marginalia
  :after vertico
  :custom
  (marginalia-annotators '(marginalia-annotators-heavy marginalia-annotators-light nil))
  :init
  (marginalia-mode))

(use-package orderless
  :ensure t
  :custom (completion-styles '(orderless)))

Org

(straight-use-package 'org)
Org Babel
(with-eval-after-load 'org
  (org-babel-do-load-languages
   'org-babel-load-languages
   '((emacs-lisp . t)
     (python . t)
     (lua . t))))

                                        ;(push '("conf-unix" . conf-unix) org-src-lang-modes))
Org Structure Templates
(with-eval-after-load 'org
  ;;;; This is needed as of Org 9.2
  (require 'org-tempo)

  (add-to-list 'org-structure-template-alist '("sh" . "src shell"))
  (add-to-list 'org-structure-template-alist '("ps" . "src powershell"))
  (add-to-list 'org-structure-template-alist '("rs" . "src rust"))
  (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 '("dt" . "src dot"))
  (add-to-list 'org-structure-template-alist '("zg" . "src zig"))
  (add-to-list 'org-structure-template-alist '("go" . "src go"))
  (add-to-list 'org-structure-template-alist '("ex" . "src elixir")))
Org Bullets

org-bullets replaces the heading stars in org-mode buffers with nicer looking characters that you can control. Another option for this is org-superstar-mode which we may cover in a later video.

(use-package org-bullets
  :hook (org-mode . org-bullets-mode)
  :custom
  (org-bullets-bullet-list '("" "" "" "" "" "" "")))
Center Org Buffers

We use visual-fill-column to center org-mode buffers for a more pleasing writing experience as it centers the contents of the buffer horizontally to seem more like you are editing a document. This is really a matter of personal preference so you can remove the block below if you don’t like the behavior.

(setq visual-fill 120)

(defun efs/org-mode-visual-fill ()
  "Function from emacs from scratch."
  (setq visual-fill-column-width visual-fill
        visual-fill-column-center-text t)
  (visual-fill-column-mode 1))

(defun my/markdown-mode-visual-fill ()
  "Function from emacs from scratch."
  (setq visual-fill-column-width visual-fill
        visual-fill-column-center-text t)
  (visual-fill-column-mode 1))

(use-package visual-fill-column
  :hook (org-mode . efs/org-mode-visual-fill)
  :hook (markdown-mode . my/markdown-mode-visual-fill))
Org Export
(use-package ox-gfm ;; Github Flavored Markdown
  :config (require 'ox-gfm))

(use-package ox-rst ;; Export to reStructuredText
  :config (require 'ox-rst))

(use-package ox-pandoc
  :if (executable-find "pandoc")
  :config (require 'ox-pandoc))
Emphasis Marker

In Org you can surround text with special characters to make them bold, italic and so on. The characters are

CharacterExampleMeaning
*Foobarbold
/Foobaritalic
" | =Foobarverbatim
" | ~Foobarcode
_Foobarunderlined
+Foobarstrike-through

To make Org files look prettier i do not show those characters by default, this however can make editing text a bit difficult, so here i define some functions to toggle this feature on an of.

(defun my/org-emphasis-markers-status ()
  "Get the status of org-hide-emphasis-markers."
  (interactive)
  (message "org-hide-emphasis-markers %s"
           (if org-hide-emphasis-markers "ON" "OFF")))

(defun my/toggle-org-hide-emphasis-markers ()
  "Toggle emphasis markers."
  (interactive)
  (setq org-hide-emphasis-markers
        (not org-hide-emphasis-markers))
  (org-mode-restart)
  (my/org-emphasis-markers-status))

(global-set-key [f9] 'my/toggle-org-hide-emphasis-markers)

Which-key

(use-package which-key
  :diminish
  :config (which-key-mode))

Evil

(setq evil-want-keybinding nil) ;; this needs to be set to nil befor evil is loaded

(use-package evil
  :init
  (setq evil-want-C-u-scroll t)
  (setq evil-want-C-i-jump nil)
  (setq evil-want-integration t)
  :after evil-leader
  :config
  (evil-mode 1)
  (define-key evil-insert-state-map (kbd "C-g") 'evil-normal-state)
  (define-key evil-insert-state-map (kbd "C-h") 'evil-delete-backward-char-and-join)

  (define-key evil-insert-state-map (kbd "C-j") 'evil-next-visual-line)
  (define-key evil-insert-state-map (kbd "C-k") 'evil-previous-visual-line)

  (define-key evil-motion-state-map (kbd "g h") 'evil-window-top)
  (define-key evil-motion-state-map (kbd "g l") 'evil-window-bottom)

  ;; Use visual line motions even outside of visual-line-mode buffers
  (evil-global-set-key 'motion "j" 'evil-next-visual-line)
  (evil-global-set-key 'motion "k" 'evil-previous-visual-line)

  (evil-set-initial-state 'messages-buffer-mode 'normal)
  (evil-set-initial-state 'dashboard-mode 'normal)

  (evil-define-key '(normal insert) org-mode-map (kbd "M-h") 'org-metaleft)
  (evil-define-key '(normal insert) org-mode-map (kbd "M-l") 'org-metaright)

  (evil-define-key '(normal insert) org-mode-map (kbd "M-H") 'org-promote-subtree)
  (evil-define-key '(normal insert) org-mode-map (kbd "M-L") 'org-demote-subtree)

  ;; Move header up and down
  (evil-define-key '(normal insert visual) org-mode-map (kbd "M-j") 'org-metadown)
  (evil-define-key '(normal insert visual) org-mode-map (kbd "M-k") 'org-metaup)

  ;; Changes priority
  (evil-define-key '(normal) org-mode-map (kbd "K") 'org-shiftup)
  (evil-define-key '(normal) org-mode-map (kbd "J") 'org-shiftdown)

  ;; Cycles through Todo Done etc.
  (evil-define-key '(normal) org-mode-map (kbd "L") 'org-shiftright)
  (evil-define-key '(normal) org-mode-map (kbd "H") 'org-shiftleft)

  (evil-define-key '(insert) org-mode-map (kbd "C-L") 'org-shiftright)
  (evil-define-key '(insert) org-mode-map (kbd "C-H") 'org-shiftleft)

  (evil-define-key '(normal insert) org-mode-map (kbd "<tab>") 'org-cycle)
  ;; DocView
  (evil-define-key '(normal insert) doc-view-mode-map (kbd "j") 'doc-view-scroll-up-or-next-page)
  (evil-define-key '(normal insert) doc-view-mode-map (kbd "k") 'doc-view-scroll-down-or-previous-page)

  (evil-define-key '(normal insert) doc-view-mode-map (kbd "J") 'doc-view-next-line-or-next-page)
  (evil-define-key '(normal insert) doc-view-mode-map (kbd "K") 'doc-view-previous-line-or-previous-page)

  (evil-define-key '(normal insert) doc-view-mode-map (kbd "M-g") 'doc-view-goto-page)

  (evil-define-key '(normal insert) doc-view-mode-map (kbd "h") 'beginning-of-buffer)
  (evil-define-key '(normal insert) doc-view-mode-map (kbd "l") 'end-of-buffer)

  (evil-define-key '(normal insert) doc-view-mode-map (kbd "M-j") 'doc-view-enlarge)
  (evil-define-key '(normal insert) doc-view-mode-map (kbd "M-k") 'doc-view-shrink)
  (evil-global-set-key 'normal (kbd "K") 'lsp-ui-doc-glance))
Evil Escape

In order to easly go back to normal mode we use “jk”.

NOTE: pressing “jk” is equivalent to pressing <ESC>

(use-package evil-escape
  :diminish
  :init (setq-default evil-escape-key-sequence "jk")
  :config (evil-escape-mode 1))
Evil Leader
                                        ;(use-package evil-leader ;; After editing the key bindings reload evil-leader and evil after that!
                                        ;  :init (global-evil-leader-mode)
                                        ;  :config (define-key evil-normal-state-map (kbd "SPC") nil)
                                        ;  (evil-leader/set-leader "<SPC>")
                                        ;  (evil-leader/set-key
                                        ;    "b" 'switch-to-buffer
                                        ;    "n" 'evil-buffer-new))

(use-package evil-leader ;; After editing the key bindings reload evil-leader and evil after that!
  :init (global-evil-leader-mode)
  :config (define-key evil-normal-state-map (kbd "SPC") nil)
  (evil-leader/set-leader "<SPC>")
  (evil-leader/set-key
    "b" 'switch-to-buffer
    "f" 'recentf-open
    "n" 'evil-buffer-new
    "r" 'reindent-buffer
    "R" 'hydra-resize-frames/body
    "t" 'hydra-toggle/body
    "o" 'hydra-org-mode/body
    "s" 'hydra-text-scale/body
    "i" 'hydra-insert-date-and-time-at-point/body
    "e" 'hydra-emacs-actions/body
    "h" 'harpoon-quick-menu-hydra
    "j" 'lsp-ui-doc-focus-frame
    "k" 'lsp-ui-doc-unfocus-frame
    "c" 'recompile
    "k" 'lsp-ui-doc-unfocus-frame))
Evil Collection
(use-package evil-collection
  :after evil
  :diminish
  :config
  (evil-collection-init))

(evil-collection-define-key 'normal 'dired-mode-map
  "h" 'dired-up-directory
  "l" 'dired-find-file)
Evil Nerd Commenter

Emacs’ built in commenting functionality comment-dwim (usually bound to M-;) doesn’t always comment things in the way you might expect so we use evil-nerd-commenter to provide a more familiar behavior. I’ve bound it to M-/ since other editors sometimes use this binding but you could also replace Emacs’ M-; binding with this command.

(use-package evil-nerd-commenter
  :bind ("M-/" . evilnc-comment-or-uncomment-lines))

Colorscheme

(use-package catppuccin-theme
  :config (setq catppuccin-flavor 'macchiato))

(load-theme 'catppuccin :no-confirm)

Window/Frame management

Window Numbering

Every Window will be asigned a number and can be selected by pressing M-{1-9}

(use-package window-numbering
  :config (window-numbering-mode))
Move Border
(straight-use-package '(move-border
                        :host github
                        :repo "ramnes/move-border"
                        :branch "master"))

(require 'move-border)

(global-set-key (kbd "C-M-j") 'move-border-down)
(global-set-key (kbd "C-M-k") 'move-border-up)
(global-set-key (kbd "C-M-h") 'move-border-left)
(global-set-key (kbd "C-M-l") 'move-border-right)

Projectile

Projectile is a project management library for Emacs which makes it a lot easier to navigate around code projects for various languages. Many packages integrate with Projectile so it’s a good idea to have it installed even if you don’t use its commands directly.

(if (is-linux) ;;
    (setq projectile-indexing-method 'native))

(use-package projectile
  :diminish projectile-mode
  :config (projectile-mode)
  :custom ((projectile-completion-system 'vertico))
  :bind-keymap
  ("C-c p" . projectile-command-map)
  :init
  ;; NOTE: Set this to the folder where you keep your Git repos!
  (when (file-directory-p "~/Projects")
    (setq projectile-project-search-path '("~/Projects")))
  (setq projectile-switch-project-action #'projectile-dired))

(use-package counsel-projectile
  :after projectile
  :config (counsel-projectile-mode))

Magit

Magit is the best Git interface I’ve ever used. Common Git operations are easy to execute quickly using Magit’s command panel system.

                                        ;(use-package sqlite)
                                        ;(use-package sqlite3)

(use-package magit
  :after sqlite
  :commands magit-status
  :custom
  (magit-display-buffer-function #'magit-display-buffer-same-window-except-diff-v1))
Forge

don’t know what it dose…

;; NOTE: Make sure to configure a GitHub token before using this package!
;; - https://magit.vc/manual/forge/Token-Creation.html#Token-Creation
;; - https://magit.vc/manual/ghub/Getting-Started.html#Getting-Started
;; (use-package forge
;;   :after magit)

Harpoon

(use-package harpoon)
Harpoon keybindings
Vanilla Emacs
;; On vanilla (You can use another prefix instead C-c h)

;; You can use this hydra menu that have all the commands
(global-set-key (kbd "C-c a") 'harpoon-quick-menu-hydra)
(global-set-key (kbd "C-c h <return>") 'harpoon-add-file)

;; And the vanilla commands
(global-set-key (kbd "C-c h f") 'harpoon-toggle-file)
(global-set-key (kbd "C-c h h") 'harpoon-toggle-quick-menu)
(global-set-key (kbd "C-c h c") 'harpoon-clear)
(global-set-key (kbd "C-c h 1") 'harpoon-go-to-1)
(global-set-key (kbd "C-c h 2") 'harpoon-go-to-2)
(global-set-key (kbd "C-c h 3") 'harpoon-go-to-3)
(global-set-key (kbd "C-c h 4") 'harpoon-go-to-4)
(global-set-key (kbd "C-c h 5") 'harpoon-go-to-5)
(global-set-key (kbd "C-c h 6") 'harpoon-go-to-6)
(global-set-key (kbd "C-c h 7") 'harpoon-go-to-7)
(global-set-key (kbd "C-c h 8") 'harpoon-go-to-8)
(global-set-key (kbd "C-c h 9") 'harpoon-go-to-9)
Doom Emacs
;; On doom emacs

;; You can use this hydra menu that have all the commands
(map! :n "C-SPC" 'harpoon-quick-menu-hydra)
(map! :n "C-s" 'harpoon-add-file)

;; And the vanilla commands
(map! :leader "j c" 'harpoon-clear)
(map! :leader "j f" 'harpoon-toggle-file)
(map! :leader "1" 'harpoon-go-to-1)
(map! :leader "2" 'harpoon-go-to-2)
(map! :leader "3" 'harpoon-go-to-3)
(map! :leader "4" 'harpoon-go-to-4)
(map! :leader "5" 'harpoon-go-to-5)
(map! :leader "6" 'harpoon-go-to-6)
(map! :leader "7" 'harpoon-go-to-7)
(map! :leader "8" 'harpoon-go-to-8)
(map! :leader "9" 'harpoon-go-to-9)

LSP

lsp-mode

We use the excellent lsp-mode to enable IDE-like functionality for many different programming languages via “language servers” that speak the Language Server Protocol. Before trying to set up lsp-mode for a particular language, check out the documentation for your language so that you can learn which language servers are available and how to install them. The lsp-keymap-prefix setting enables you to define a prefix for where lsp-mode’s default keybindings will be added. I highly recommend using the prefix to find out what you can do with lsp-mode in a buffer. The which-key integration adds helpful descriptions of the various keys so you should be able to learn a lot just by pressing C-c l in a lsp-mode buffer and trying different things that you find there.

(defun efs/lsp-mode-setup ()
  "Function from emacs from scratch."
  (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 . efs/lsp-mode-setup)
  :init
  (setq lsp-keymap-prefix "C-c l")  ;; Or 'C-l', 's-l'
  :config
  (lsp-enable-which-key-integration t))
lsp-ui

lsp-ui is a set of UI enhancements built on top of lsp-mode which make Emacs feel even more like an IDE. Check out the screenshots on the lsp-ui homepage (linked at the beginning of this paragraph) to see examples of what it can do.

(use-package lsp-ui
  :hook (lsp-mode . lsp-ui-mode)
  :custom
  (lsp-ui-doc-position 'bottom))
lsp-treemacs

lsp-treemacs provides nice tree views for different aspects of your code like symbols in a file, references of a symbol, or diagnostic messages (errors and warnings) that are found in your code.

Try these commands with M-x:

  • lsp-treemacs-symbols - Show a tree view of the symbols in the current file
  • lsp-treemacs-references - Show a tree view for the references of the symbol under the cursor
  • lsp-treemacs-error-list - Show a tree view for the diagnostic messages in the project

    This package is built on the treemacs package which might be of some interest to you if you like to have a file browser at the left side of your screen in your editor.

    (use-package lsp-treemacs
      :after lsp)
    
        

Debugging with dap-mode

dap-mode is an excellent package for bringing rich debugging capabilities to Emacs via the Debug Adapter Protocol. You should check out the configuration docs to learn how to configure the debugger for your language. Also make sure to check out the documentation for the debug adapter to see what configuration parameters are available to use for your debug templates!

(use-package dap-mode
  ;; Uncomment the config below if you want all UI panes to be hidden by default!
  ;; :custom
  ;; (lsp-enable-dap-auto-configure nil)
  ;; :config
  ;; (dap-ui-mode 1)
  :commands dap-debug
  :config
  ;; Set up Node debugging
  (require 'dap-node)
  (dap-node-setup) ;; Automatically installs Node debug adapter if needed

  ;; Bind `C-c l d` to `dap-hydra` for easy access
                                        ;(general-define-key
                                        ; :keymaps 'lsp-mode-map
                                        ; :prefix lsp-keymap-prefix
                                        ; "d" '(dap-hydra t :wk "debugger"))
  )

Company

Company Mode provides a nicer in-buffer completion interface than completion-at-point which is more reminiscent of what you would expect from an IDE. We add a simple configuration to make the keybindings a little more useful (TAB now completes the selection and initiates completion at the current location if needed).

We also use company-box to further enhance the look of the completions with icons and better overall presentation.

(use-package company
  :after lsp-mode
  :hook (lsp-mode . company-mode)
  :bind (:map company-active-map
              ("<tab>" . company-complete-selection))
  (:map lsp-mode-map
        ("<tab>" . company-indent-or-complete-common))
  :custom
  (company-minimum-prefix-length 2)
  (company-idle-delay 0.0))

(use-package company-box
  :hook (company-mode . company-box-mode))

Flycheck

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

Yasnippet

(use-package yasnippet)
(use-package yasnippet-snippets)

All The Icons

NOTE If you install all-the-icons for the first time run all-the-incons-install-fonts

(use-package all-the-icons)

Doom Mode Line

(use-package doom-modeline
  :init (doom-modeline-mode 1)
  :custom ((doom-modeline-height 15)))

Hydra

(use-package hydra
  :defer t)
Hydras
Emacs Actions
(defhydra hydra-emacs-actions (:timeout 5)
  "actions"
  ("g" lsp-ui-doc-show "display hover information" :exit t))
Toggle stuff
(defhydra hydra-toggle (:timeout 5)
  "toggle"
  ("t" toggle-truncate-lines "truncate lines" :exit t)
  ("l" display-line-numbers-mode "line numbers" :exit t)
  ("c" visual-fill-column-mode "center text in buffers" :exit t)
  ("d" display-fill-column-indicator-mode "column indicator" :exit t)
  ("e" my/toggle-org-hide-emphasis-markers "emphasis-markers" :exit t))
Text Scaling

This is an example of using Hydra to design a transient key binding for quickly adjusting the scale of the text on screen. We define a hydra that is bound to C-s t s and, once activated, j and k increase and decrease the text scale. You can press any other key (or f specifically) to exit the transient key map.

(defhydra hydra-text-scale (:timeout 5)
  "scale text"
  ("j" text-scale-increase "in")
  ("k" text-scale-decrease "out")
  ("f" nil "finished" :exit t))
Insert date time at point
(defhydra hydra-insert-date-and-time-at-point ()
  "insert date and time at point"
  ("n" now "insert date and time" :exit t)
  ("t" today "insert date time long" :exit t))
Org-mode Stuff
(defhydra hydra-org-mode ()
  "org mode"
  ("t" org-babel-tangle "tangle current org file" :exit t)
  ("e" org-export-dispatch "export current org buffer" :exit t))
Resize Frames
(defhydra hydra-resize-frames ()
  "resize frames"
  ("j" move-border-down  "move border down")
  ("k" move-border-up    "move border up")
  ("h" move-border-left  "move border left")
  ("l" move-border-right "move border right")
  ("f" nil "finished" :exit t))

one.el

(straight-use-package
 '(one :type git :host github :repo "tonyaldon/one.el"
       :build (:not compile)))

Diminish

(diminish 'undo-tree-mode)
(diminish 'eldoc-mode)
(diminish 'auto-revert-mode)
(diminish 'flycheck-mode)
(diminish 'company-mode)
(diminish 'dotnet-mode)
(diminish 'counsel-mode)
(diminish 'list-interaction-mode)
(diminish 'evil-collection-unimpaired-mode)
(diminish 'which-key-mode)

Other Stuff

The stuff here is all the stuff i don’t want to be part of the initial config. I load the stuff through the ~/.myinitel if needed. All codeblocks are going to be put inside the ~/.emacs.d/conf folder.

cc.el

(add-hook 'cc-mode 'lsp-deferred)

dotnet.el

(add-to-list 'auto-mode-alist '("\\.fsproj\\'" . xml-mode))
(add-to-list 'auto-mode-alist '("\\.axaml\\'" . xml-mode))
(add-to-list 'auto-mode-alist '("\\.xaml\\'" . xml-mode))
(add-to-list 'auto-mode-alist '("\\.csproj\\'" . xml-mode))

(if (< emacs-major-version 29)
    (use-package csharp-mode
      :defer t
      :after dotnet))

(use-package fsharp-mode
  :defer t
  :after dotnet)

(use-package dotnet
  :hook (fsharp-mode . dotnet-mode)
  :hook (csharp-mode . dotnet-mode)
  :hook (xml-mode . dotnet-mode)
  :hook (dotnet-mode . lsp-deferred)
  :bind (:map dotnet-mode-map ("<f5>" . dotnet-run)))

beam.el

(use-package elixir-mode
  :hook (elixir-mode . lsp-deferred)
  :hook (elixir-mode . yas-minor-mode))

(use-package mix
  :defer t)

(use-package erlang
  :defer t)

(use-package edts
  :defer t)

go.el

(use-package go-mode
  :defer t)

graphviz.el

(use-package graphviz-dot-mode
  :defer t
  :config
  (setq graphviz-dot-indent-width 4))

haskell.el

(use-package haskell-mode
  :defer t)

java.el

(use-package javap-mode
  :defer t)
(use-package kotlin-mode
  :defer t) ;; for gradle kotlin script files
(use-package scala-mode
  :defer t)

(use-package lsp-java
  :hook (java-mode . lsp)
  :hook (scala-mode . lsp)
  :hook (kotlin-mode . lsp))

(add-to-list 'auto-mode-alist '("\\.kts\\'" . kotlin-mode))

clojure.el

(use-package clojure-mode
  :defer t)
(use-package cider
  :defer t)

(when (eq system-type 'gnu/linux)
  (setq exec-path (append exec-path '("~/bin/"))))

jvm.el

(use-package clojure-mode
  :defer t)

(use-package cider
  :defer t)

(use-package javap-mode
  :defer t)

(use-package kotlin-mode
  :defer t) ;; for gradle kotlin script files

(use-package scala-mode
  :defer t)

(use-package groovy-mode
  :defer t)

(use-package lsp-java
  :hook (java-mode . lsp)
  :hook (kotlin-mode . lsp)
  :hook (scala-mode . lsp))

(add-to-list 'auto-mode-alist '("\\.kts\\'" . kotlin-mode))

(when (eq system-type 'gnu/linux)
  (setq exec-path (append exec-path '("~/bin/"))))

lua.el

(use-package lua-mode
  :defer t)

nix.el

(use-package nix-mode
  :defer t)
(use-package nix-buffer
  :defer t)

ocaml.el

(add-to-list 'load-path "C:\Users\thomas\AppData\Local\opam\playground\share/emacs/site-lisp")
(require 'ocp-indent)

(let ((opam-share (ignore-errors (car (process-lines "opam" "var" "share")))))
  (when (and opam-share (file-directory-p opam-share))
    ;; Register Merlin
    (add-to-list 'load-path (expand-file-name "emacs/site-lisp" opam-share))
    (autoload 'merlin-mode "merlin" nil t nil)
    ;; Automatically start it in OCaml buffers
    (add-hook 'tuareg-mode-hook 'merlin-mode t)
    (add-hook 'caml-mode-hook 'merlin-mode t)
    ;; Use opam switch to lookup ocamlmerlin binary
    (setq merlin-command 'opam)))

(use-package tuareg-mode
  :defer t)

php.el

(use-package php-mode
  :defer t)

powershell.el

(use-package powershell
  :defer t)

python.el

(use-package pyenv-mode
  :defer t)
(use-package kivy-mode
  :defer t)

racket.el

(use-package racket-mode
  :defer t)
(use-package geiser
  :defer t)
(use-package geiser-racket
  :defer t)

rust.el

(use-package rust-mode
  :hook (rust-mode . lsp-deferred))

(use-package toml-mode
  :defer t)
(add-to-list 'auto-mode-alist '("\\.toml\\'" . toml-mode))

(use-package cargo
  :defer t)

(use-package cargo-mode
  :hook (rust-mode . cargo-minor-mode))

typescript.el

(use-package typescript-mode
  :mode "\\.ts\\'"
  :hook (typescript-mode . lsp-deferred)
  :config
  (setq typescript-indent-level 2))

yaml.el

(use-package yaml-mode
  :defer t)
(add-to-list 'auto-mode-alist '("\\.yml\\'" . yaml-mode))
(add-to-list 'auto-mode-alist '("\\.yaml\\'" . yaml-mode))

zig.el

(use-package zig-mode
  :defer t
  :hook (zig-mode . lsp-deferred))

flutter_and_dart.el

(if (is-linux)
    (progn
      (setq exec-path (append exec-path (list (prefix-with-home "bin/flutter/bin") (prefix-with-home "/home/thomas/bin/flutter/bin/cache/dart-sdk/bin"))))
      (setq lsp-dart-flutter-sdk-dir (prefix-with-home "bin/flutter"))
      (setq lsp-dart-sdk-dir (prefix-with-home "bin/flutter/bin/cache/dart-sdk"))))

(load-file "~/.emacs.d/conf/yaml.el")

(use-package flutter
  :defer t)

(use-package dart-mode
  :defer t)

(use-package lsp-dart
  :defer t)

Custom set variables

(setq custom-file (concat *emacsd-directory* "custom-set-variables.el"))

(unless (file-exists-p custom-file)
  (write-region "" nil custom-file))

(setq zig-exe-path (prefix-with-userprofile-or-home ".zvm/bin/zig.exe"))
(setq zig-exe-path (prefix-with-userprofile-or-home ".zvm/bin/zig"))

(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.
 '(zig-zig-bin zig-exe-path)
 '(warning-suppress-types '((use-package) (comp))))

(load-file custom-file)

End

(cd "~")
(if (file-exists-p *myinitel*)
    (load-file *myinitel*))
(provide 'init)
;;; init.el ends here