dotfiles/.emacs.d/settings.org

29 KiB
Raw Blame History

Ezri's Settings

Shamelessly stole this from Simponic, made some modifications myself.

Packages

Melpa

  (require 'package)
  (add-to-list 'package-archives
               '("melpa" . "https://melpa.org/packages/") t)

Project

  (use-package project
  	:ensure t)

Configure some packages for internal only

  (use-package eldoc :straight (:type built-in))
  (use-package flymake :straight (:type built-in))

General emacs

Indentation

Indent using tabs, render with tab-width of 2.

  (use-package smart-tabs-mode
  	:ensure t
  	;; :init
  	;; (smart-tabs-insinuate 'c 'c++ 'java 'javascript 'python)
  	)
  (setq default-tab-width 2)
  (setq-default tab-width 2)
  (setq-default indent-tabs-mode t)
  (setq sh-indentation 2)

  (add-hook 'conf-mode-hook
            (lambda ()
              (setq indent-line-function #'insert-tab
                    indent-tabs-mode t)))
  (add-hook 'nftables-mode-hook
            (lambda ()
              (setq indent-tabs-mode nil)))

Line numbers

  (global-display-line-numbers-mode)

Filesystem stuff

  (setq auto-save-default nil)
  (setq make-backup-files nil)
  (setq create-lockfiles nil)
  (global-auto-revert-mode t) ;; Change files on disk as they are updated

UI stuff

  ;; (when (window-system)
  ;;   (menu-bar-mode -1)
  ;;   (tool-bar-mode -1)
  ;;   (toggle-scroll-bar -1)
  ;;   (if (display-graphic-p)
  ;;       (funcall (lambda ()
  ;;                  (set-fringe-mode '(1 . 1))
  ;;                  )))
  ;;   (setq frame-resize-pixelwise t))

  (setq inhibit-startup-screen t)

  (defun my-frame-config (&optional frame)
    (setq frame-resize-pixelwise t)
    (if (display-graphic-p)
        (set-fringe-mode '(1 . 1)))
    (if (not frame) ;; The initial call, run when emacs starts
        (funcall (lambda ()
                   (menu-bar-mode -1)
                   (tool-bar-mode -1)
                   (toggle-scroll-bar -1)
                   )))
    ;;-----------------------------------------;;
    ;; reinitialize modes in case of new frame ;;
    ;;-----------------------------------------;;
    (if menu-bar-mode
        (menu-bar-mode -1))
    (if tool-bar-mode
        (tool-bar-mode -1))
    (if scroll-bar-mode
        (scroll-bar-mode -1)))

  (my-frame-config) ;; Run initially so that direct invocations work
  (add-hook 'after-make-frame-functions 'my-frame-config)

TUI stuff

  (defun terminal-config (&optional frame)
    "Establish settings for teh current terminal."
    (if (not frame) ;; The initial call.
        (xterm-mouse-mode 1)
      (if xterm-mouse-mode
          ;; Re-initialize the mode in case of a new terminal.
          (xterm-mouse-mode 1))))

  (terminal-config)
  (add-hook 'after-make-frame-functions 'terminal-config)

Custom keymap

  (global-set-key (kbd "C-;") 'comment-or-uncomment-region)

System path (macos)

  ;; Use system path on macos - needed for node
  (use-package exec-path-from-shell
    :ensure t
    :init
    (when (memq window-system '(mac ns x))
      (exec-path-from-shell-initialize)))

Execute command to buffer

  (defun shell-command-capture-output (command)
    (interactive "sShell command: ")
    ;; run shell command
    (with-output-to-temp-buffer "*Shell Command Output*"
      (shell-command command "*Shell Command Output*")
      (pop-to-buffer "*Shell Command Output*")
      ;; make buffer read-only
      (read-only-mode)))

IRC

Default Configuration

  (defvar irc-configured nil)

  (defun do-irc-setup ()
  	(setopt rcirc-default-nick "netsorc")
  	(setopt rcirc-default-full-name "Networking Sorceress")
  	(condition-case nil
  			(lambda () ((setopt rcirc-authinfo
  							 `(("irc.libera.chat" nickserv "netsorc" ,(secrets-get-secret "Default keyring" "libera.chat"))))
  									(setq irc-configured t)))
  		(error (message "Unable to configure IRC, keyring not unlocked.")))
  	(message "IRC configured."))

  (defun irc-setup ()
  	(if irc-configured (message "IRC configured.") (do-irc-setup)))

  (add-hook 'after-make-frame-functions 'irc-setup)
  (irc-setup)

Terminal

  (use-package vterm
  	:ensure t)

TRAMP Config

  (with-eval-after-load 'tramp (tramp-enable-method "run0"))

Theming

Highlight current line

  (global-hl-line-mode)

Font

  (add-to-list 'default-frame-alist '(font . "JetBrains Mono-9"))

Doom-themes

  (defun my-theme-config (&optional frame)    
    (use-package doom-themes
      :ensure t
      :config
      ;; Global settings (defaults)
      (setq doom-themes-enable-bold t    ; if nil, bold is universally disabled
            doom-themes-enable-italic t) ; if nil, italics is universally disabled
      (load-theme 'doom-personal t)

      ;; Enable flashing mode-line on errors
      (doom-themes-visual-bell-config)
      ;; Enable custom neotree theme (all-the-icons must be installed!)
      (doom-themes-neotree-config)
      ;; or for treemacs users
      (setq doom-themes-treemacs-theme "doom-atom") ; use "doom-colors" for less minimal icon theme
      (doom-themes-treemacs-config)
      ;; Corrects (and improves) org-mode's native fontification.
      (doom-themes-org-config)))
  (my-theme-config)
  (add-hook 'after-make-frame-functions 'my-theme-config)

Doom-modeline

  (defun my-modeline-config (&optional frame)
    (use-package doom-modeline
      :ensure t
      :init (doom-modeline-mode 1)))
  (my-modeline-config)
  (add-hook 'after-make-frame-functions 'my-modeline-config)

All the icons

  (use-package all-the-icons
    :ensure t)

Tabs

  (defun my/set-tab-theme ()
    (let ((bg (face-attribute 'mode-line :background))
          (fg (face-attribute 'default :foreground))
    (hg (face-attribute 'default :background))
          (base (face-attribute 'mode-line :background))
          (box-width (/ (line-pixel-height) 4)))
      (set-face-attribute 'tab-line nil
        :background base
        :foreground fg
        :height 0.8
        :inherit nil
        :box (list :line-width -1 :color base)
        )
      (set-face-attribute 'tab-line-tab nil
        :foreground fg
        :background bg
        :weight 'normal
        :inherit nil
        :box (list :line-width box-width :color bg))
      (set-face-attribute 'tab-line-tab-inactive nil
        :foreground fg
        :background base
        :weight 'normal
        :inherit nil
        :box (list :line-width box-width :color base))
      (set-face-attribute 'tab-line-highlight nil
        :foreground fg
        :background hg
        :weight 'normal
        :inherit nil
        :box (list :line-width box-width :color hg))
      (set-face-attribute 'tab-line-tab-current nil
        :foreground fg
        :background hg
        :weight 'normal
        :inherit nil
        :box (list :line-width box-width :color hg))))

  (defun my/tab-line-name-buffer (buffer &rest _buffers)
    "Create name for tab with padding and truncation.

  If buffer name is shorter than `tab-line-tab-max-width' it gets
  centered with spaces, otherwise it is truncated, to preserve
  equal width for all tabs.  This function also tries to fit as
  many tabs in window as possible, so if there are no room for tabs
  with maximum width, it calculates new width for each tab and
  truncates text if needed.  Minimal width can be set with
  `tab-line-tab-min-width' variable."
    (with-current-buffer buffer
      (let* ((window-width (window-width (get-buffer-window)))
             (tab-amount (length (tab-line-tabs-window-buffers)))
             (window-max-tab-width (if (>= (* (+ tab-line-tab-max-width 3) tab-amount) window-width)
                                       (/ window-width tab-amount)
                                     tab-line-tab-max-width))
             (tab-width (- (cond ((> window-max-tab-width tab-line-tab-max-width)
                                  tab-line-tab-max-width)
                                 ((< window-max-tab-width tab-line-tab-min-width)
                                  tab-line-tab-min-width)
                                 (t window-max-tab-width))
                           3)) ;; compensation for ' x ' button
             (buffer-name (string-trim (buffer-name)))
             (name-width (length buffer-name)))
        (if (>= name-width tab-width)
            (concat  " " (truncate-string-to-width buffer-name (- tab-width 2)) "…")
          (let* ((padding (make-string (+ (/ (- tab-width name-width) 2) 1) ?\s))
                 (buffer-name (concat padding buffer-name)))
            (concat buffer-name (make-string (- tab-width (length buffer-name)) ?\s)))))))

  (defun tab-line-close-tab (&optional e)
    "Close the selected tab.

  If tab is presented in another window, close the tab by using
  `bury-buffer` function.  If tab is unique to all existing
  windows, kill the buffer with `kill-buffer` function.  Lastly, if
  no tabs left in the window, it is deleted with `delete-window`
  function."
    (interactive "e")
    (let* ((posnp (event-start e))
           (window (posn-window posnp))
           (buffer (get-pos-property 1 'tab (car (posn-string posnp)))))
      (with-selected-window window
        (let ((tab-list (tab-line-tabs-window-buffers))
              (buffer-list (flatten-list
                            (seq-reduce (lambda (list window)
                                          (select-window window t)
                                          (cons (tab-line-tabs-window-buffers) list))
                                        (window-list) nil))))
          (select-window window)
          (if (> (seq-count (lambda (b) (eq b buffer)) buffer-list) 1)
              (progn
                (if (eq buffer (current-buffer))
                    (bury-buffer)
                  (set-window-prev-buffers window (assq-delete-all buffer (window-prev-buffers)))
                  (set-window-next-buffers window (delq buffer (window-next-buffers))))
                (unless (cdr tab-list)
                  (ignore-errors (delete-window window))))
            (and (kill-buffer buffer)
                 (unless (cdr tab-list)
                   (ignore-errors (delete-window window)))))))))

  (unless (version< emacs-version "27")
    (use-package tab-line
      :ensure nil
      :hook (after-init . global-tab-line-mode)
      :config

      (defcustom tab-line-tab-min-width 10
        "Minimum width of a tab in characters."
        :type 'integer
        :group 'tab-line)

      (defcustom tab-line-tab-max-width 30
        "Maximum width of a tab in characters."
        :type 'integer
        :group 'tab-line)

      (setq tab-line-close-button-show t
            tab-line-new-button-show nil
            tab-line-separator ""
            tab-line-tab-name-function #'my/tab-line-name-buffer
            tab-line-right-button (propertize (if (char-displayable-p ?▶) " ▶ " " > ")
                                              'keymap tab-line-right-map
                                              'mouse-face 'tab-line-highlight
                                              'help-echo "Click to scroll right")
            tab-line-left-button (propertize (if (char-displayable-p ?◀) " ◀ " " < ")
                                             'keymap tab-line-left-map
                                             'mouse-face 'tab-line-highlight
                                             'help-echo "Click to scroll left")
            tab-line-close-button (propertize (if (char-displayable-p ?×) " × " " x ")
                                              'keymap tab-line-tab-close-map
                                              'mouse-face 'tab-line-close-highlight
                                              'help-echo "Click to close tab"))

      (my/set-tab-theme)

      ;;(dolist (mode '(ediff-mode process-menu-mode term-mode vterm-mode))
      ;;(add-to-list 'tab-line-exclude-modes mode))
      (dolist (mode '(ediff-mode process-menu-mode))
        (add-to-list 'tab-line-exclude-modes mode))
      ))

  (defun my-tab-config (&optional frame)
    "if frame is a terminal, disable tab-line-mode"
    (when (not (display-graphic-p frame))
      (tab-line-mode nil)))

  (global-tab-line-mode t)

  (add-hook 'after-make-frame-functions 'my-tab-config)

Projectile

  (use-package projectile
    :bind ("C-c p" . 'projectile-command-map)
    :init (projectile-mode +1) (setq projectile-enable-caching t)
    :ensure t)

Swiper, Ivy

  (use-package counsel
    :ensure t
    :bind
    ("C-s" . 'swiper-isearch)
    ("M-x" . 'counsel-M-x)
    :init
    (setq ivy-use-virtual-buffers t)
    (setq enable-recursive-minibuffers t)
    (ivy-mode 1))

Neotree

  (use-package neotree
    :ensure t
    :bind ("C-c j" . 'neotree-toggle)
    :init
    ;; slow rendering
    (setq inhibit-compacting-font-caches t)

    ;; set icons theme
    (setq neo-theme (if (display-graphic-p) 'icons 'arrow))

    ;; Every time when the neotree window is opened, let it find current file and jump to node
    (setq neo-smart-open t)

    ;; When running projectile-switch-project (C-c p p), neotree will change root automatically
    (setq projectile-switch-project-action 'neotree-projectile-action)

    (setq neo-window-width 35)

    ;; show hidden files
    (setq-default neo-show-hidden-files t))

Custom Mode Bindings

SystemD unit files

  ;; ;; Base systemd unit files
  ;; (add-to-list 'auto-mode-alist '("\\.service\\'" . conf-unix-mode))
  ;; (add-to-list 'auto-mode-alist '("\\.timer\\'" . conf-unix-mode))
  ;; (add-to-list 'auto-mode-alist '("\\.mount\\'" . conf-unix-mode))
  ;; (add-to-list 'auto-mode-alist '("\\.automount\\'" . conf-unix-mode))
  ;; (add-to-list 'auto-mode-alist '("\\.target\\'" . conf-unix-mode))
  ;; (add-to-list 'auto-mode-alist '("\\.path\\'" . conf-unix-mode))
  ;; (add-to-list 'auto-mode-alist '("\\.slice\\'" . conf-unix-mode))
  ;; (add-to-list 'auto-mode-alist '("\\.socket\\'" . conf-unix-mode))
  ;; (add-to-list 'auto-mode-alist '("\\.device\\'" . conf-unix-mode))
  ;; ;; systemd-networkd
  ;; (add-to-list 'auto-mode-alist '("\\.network\\'" . conf-unix-mode))
  ;; (add-to-list 'auto-mode-alist '("\\.link\\'" . conf-unix-mode))
  ;; (add-to-list 'auto-mode-alist '("\\.netdev\\'" . conf-unix-mode))
  (use-package systemd
  	:ensure t)

elkowar's wacky widgets

  (add-to-list 'auto-mode-alist '("\\.yuck\\'" . conf-unix-mode))

Webdev

  (add-to-list 'auto-mode-alist '("\\.tsx\\'" . typescript-mode))

Config & Markup

Markdown

Auto Text Wrap

  (use-package visual-fill-column
  	:ensure t
  	:init
  	(add-hook 'markdown-mode-hook (lambda ()
  																	(setq fill-column 85)
  																	(visual-fill-column-mode)
  																	(visual-line-mode)
  																	(display-fill-column-indicator-mode))))

YAML

  (use-package yaml-mode
    :ensure t
  	:mode (("\\.yml\\'" . yaml-mode)
  				 ("\\.yaml\\'" . yaml-mode)))

Org mode

General

  (setq org-startup-indented t)
  (setq org-hide-emphasis-markers t)
  (font-lock-add-keywords 'org-mode
  												'(("^ *\\([-]\\) "
  													 (0 (prog1 () (compose-region (match-beginning 1) (match-end 1) "•"))))))

Fonts

  (custom-theme-set-faces
   'user
   '(org-block ((t (:inherit fixed-pitch))))
   '(org-code ((t (:inherit (shadow fixed-pitch)))))
   '(org-document-info ((t (:foreground "dark orange"))))
   '(org-document-info-keyword ((t (:inherit (shadow fixed-pitch)))))
   '(org-indent ((t (:inherit (org-hide fixed-pitch)))))
   '(org-link ((t (:foreground "royal blue" :underline t))))
   '(org-meta-line ((t (:inherit (font-lock-comment-face fixed-pitch)))))
   '(org-property-value ((t (:inherit fixed-pitch))) t)
   '(org-special-keyword ((t (:inherit (font-lock-comment-face fixed-pitch)))))
   '(org-table ((t (:inherit fixed-pitch :foreground "#83a598"))))
   '(org-tag ((t (:inherit (shadow fixed-pitch) :weight bold :height 0.8))))
   '(org-verbatim ((t (:inherit (shadow fixed-pitch))))))


  (defun my-org-font-config (&optional frame)
  	
  	(let* ((variable-tuple
  					(cond ((x-list-fonts "Source Sans Pro") '(:font "Source Sans Pro"))
  								((x-list-fonts "Lucida Grande")   '(:font "Lucida Grande"))
  								((x-list-fonts "Verdana")         '(:font "Verdana"))
  								((x-family-fonts "Sans Serif")    '(:family "Sans Serif"))
  								(nil (warn "Cannot find a Sans Serif Font.  Install Source Sans Pro."))))
           (headline           `(:weight bold)))

  		(custom-theme-set-faces
       'user
       `(org-level-8 ((t (,@headline ,@variable-tuple))))
       `(org-level-7 ((t (,@headline ,@variable-tuple))))
       `(org-level-6 ((t (,@headline ,@variable-tuple))))
       `(org-level-5 ((t (,@headline ,@variable-tuple))))
       `(org-level-4 ((t (,@headline ,@variable-tuple :height 1.1))))
       `(org-level-3 ((t (,@headline ,@variable-tuple :height 1.25))))
       `(org-level-2 ((t (,@headline ,@variable-tuple :height 1.5))))
       `(org-level-1 ((t (,@headline ,@variable-tuple :height 1.75))))
       `(org-document-title ((t (,@headline ,@variable-tuple :height 2.0 :underline nil))))))
  	)

  (add-hook 'after-make-frame-functions 'my-org-font-config)

  (add-hook 'org-mode-hook
  					(lambda ()
  						(variable-pitch-mode)
  						(visual-line-mode)
  						(setq cursor-type '(bar . 2))
  						))

RPG Stuff

  (use-package ox-dnd
  	:straight (ox-dnd :type git :host github :repo "xeals/emacs-org-dnd" :files ("*.el"))
  	:ensure t
  	:init
  	(require 'ox-dnd)
  	)

Auto Text Wrap

  ;; (add-hook 'org-mode-hook (lambda ()
  ;;                            (setq fill-column 85)
  ;;                            (visual-fill-column-mode)
  ;;                            (visual-line-mode)))

Babel

Elixir

  (use-package ob-elixir
     :ensure t)

Load Languages

  (org-babel-do-load-languages
   'org-babel-load-languages
   '((lisp . t)
     (elixir . t)
     (emacs-lisp . t)
     (python . t)))

org-bullets

  (use-package org-bullets
    :ensure t
    :init
    (add-hook 'org-mode-hook (lambda () (org-bullets-mode 1))))

org-appear

  (use-package org-appear
    :ensure t
    :init
    (add-hook 'org-mode-hook 'org-appear-mode))

Presentations

  (use-package org-present
    :ensure t
    :straight '(org-present
                :type git
                :host github
                :repo "rlister/org-present"))

Links & Backlinks

  (use-package org-super-links
    :straight (org-super-links :type git :host github :repo "toshism/org-super-links" :branch "develop")
    :bind (("C-c s s" . org-super-links-link)
           ("C-c s l" . org-super-links-store-link)
           ("C-c s C-l" . org-super-links-insert-link))
  	:config ((require 'org-id)
  					 (setq org-id-link-to-org-use-id 'create-if-interactive-and-no-custom-id)))

Emoji Input

  (add-hook 'org-mode-hook '(lambda () (set-input-method "emoji")))

Development

Copilot

  ;; Ensure dependencies are installed
  (use-package editorconfig
    :ensure t)
  (use-package jsonrpc
    :ensure t)
  ;; Load copilot
  (use-package copilot
    :straight (copilot :type git :host github :repo "copilot-emacs/copilot.el" :files ("*.el"))
    :ensure t
    :init
    (add-hook 'prog-mode-hook 'copilot-mode)
    :bind
    (:map copilot-completion-map
          ("M-<return>" . copilot-accept-completion)
          ("M-RET" . copilot-accept-completion))
    )

Tree-Sitter

    (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")
         (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")
  			 (cython "https://github.com/b0o/tree-sitter-cython")))

Autocomplete

  (use-package auto-complete :ensure t)
  (ac-config-default)
  (defun my-tab ()
    (interactive)
    (or (copilot-accept-completion)
        (ac-expand nil)))

  (with-eval-after-load 'auto-complete
    ; diable inline preview
    (setq ac-disable-inline t)
    ; show menu if have only one candidate
    (setq ac-candidate-menu-min 0))

Company mode

  (use-package company
    :ensure t
  	:init (global-company-mode t)
    :bind (:map company-active-map
                ("C-n" . company-select-next)
                ("C-p" . company-select-previous))
    :config
    (setq company-idle-delay 0.3))
company-select-previous

LSP

  (use-package eglot
    :ensure t
    :defer t
    :bind (:map eglot-mode-map
                ("C-c C-e" . eglot-rename)
                ("C-." . eglot-code-actions)
  							("<f2>" . eglot-find-implementation))
    :hook ((python-ts-mode . eglot-ensure)
           (python-ts-mode . flyspell-prog-mode)
           (python-ts-mode . superword-mode)
           (python-ts-mode . hs-minor-mode)
  				 (typescript-ts-mode . eglot-ensure)
  				 (typescript-ts-mode . flyspell-prog-mode)
  				 (typescript-ts-mode . superword-mode)
  				 (typescript-ts-mode . hs-minor-mode)
  				 (tsx-ts-mode . eglot-ensure)
  				 (tsx-ts-mode . flyspell-prog-mode)
  				 (tsx-ts-mode . superword-mode)
  				 (tsx-ts-mode . hs-minor-mode)
  				 (typescript-mode . eglot-ensure)
  				 (typescript-mode . flyspell-prog-mode)
  				 (typescript-mode . superword-mode)
  				 (typescript-mode . hs-minor-mode))
    :config
  	(add-to-list 'eglot-server-programs '(python-base-mode . ("pylsp")))
    (setq-default eglot-workspace-configuration
                  '((:pylsp . (:configurationSources ["flake8"]
  																									 :plugins (
                                                               :mccabe (:enabled :json-false)
                                                               :pyflakes (:enabled :json-false)
                                                               :flake8 (:enabled :json-false
                                                                                 :maxLineLength 88)
                                                               :ruff (:enabled t :lineLength 88)
                                                               :pydocstyle (:enabled t :convention "numpy")
                                                               :yapf (:enabled :json-false)
                                                               :autopep8 (:enabled :json-false)
                                                               :black (:enabled t :line_length 88 :cache_config t)
  																														 :mypy (:enabled t))
  																									 )))))

Git

Magit

  (use-package magit :ensure t)

Blame

  (use-package blamer
  	:straight (:host github :repo "artawower/blamer.el")
  	:bind (("s-i" . blamer-show-commit-info))
  	:custom
  	(blamer-idle-time 0.3)
  	(blamer-min-offset 70)
  	:custom-face
  	(blamer-face ((t :foreground "#7a88cf"
  									 :background nil
  									 :italic t)))
  	:config
  	(global-blamer-mode 1))

Languages

Python

  (use-package pet
  	:config
  	(add-hook 'python-ts-mode-hook 'pet-mode -10)
  	)

Cython

Elixir

  (use-package elixir-mode
    :ensure t
    :hook ((before-save .
                        (lambda ()
                          (when (eq major-mode 'elixir-mode)
                            (elixir-format))))))

Rust

After installing the rust-analyzer program, the following can be used:

  (use-package rust-mode
    :ensure t)
  (setq lsp-rust-server 'rust-analyzer)

Vue

  (add-hook 'mmm-mode-hook
            (lambda ()
              (set-face-background 'mmm-default-submode-face nil)))

Web Stuff

Typescript
  (use-package typescript-mode
  	:ensure t
  	:mode "\\.ts\\'"
  	:config
  	(setq typescript-indent-level 2))

  (add-to-list 'auto-mode-alist '("\\.tsx\\'" . tsx-ts-mode))
TIDE
  (defun setup-tide-mode ()
    (interactive)
    (tide-setup)
    (flycheck-mode +1)
    (setq flycheck-check-syntax-automatically '(save mode-enabled))
    (eldoc-mode +1)
    (tide-hl-identifier-mode +1)
    ;; company is an optional dependency. You have to
    ;; install it separately via package-install
    ;; `M-x package-install [ret] company`
    (company-mode +1))

  (use-package tide
    :ensure t
    :after (typescript-mode company flycheck)
    :hook ((typescript-mode . setup-tide-mode)   ;; TODO: Update to tree-sitter in Emacs 29
           (js2-mode . setup-tide-mode)))
Web Mode
  ;; web-mode
  (setq web-mode-markup-indent-offset 2)
  (setq web-mode-code-indent-offset 2)
  (setq web-mode-css-indent-offset 2)
  (use-package web-mode
    :ensure t
    :mode (("\\.scss\\'" . web-mode)
           ("\\.css\\'" . web-mode)
           ("\\.jsx\\'" .  web-mode)
           ("\\.html\\'" . web-mode))
    :commands web-mode)
Prettier
  (use-package prettier-js
    :ensure t)
  (add-hook 'js2-mode-hook 'prettier-js-mode)
  (add-hook 'typescript-mode 'prettier-js-mode)
  (add-hook 'web-mode-hook 'prettier-js-mode)
Prisma
  (use-package prisma-mode
    :ensure t
    :straight '(prisma-mode
                :type git
                :host github
                :repo "pimeys/emacs-prisma-mode"))
Svelte
  (use-package svelte-mode
    :ensure t
    :straight '(svelte-mode
                :type git
                :host github
                :repo "leafOfTree/svelte-mode"))

Kotlin

  (use-package kotlin-mode
    :ensure t)

Java

  (use-package lsp-java
    :config (add-hook 'java-mode-hook 'lsp)
    :ensure t)
t

PHP

  (use-package php-mode
    :ensure t)

Format All The Buffers

  (use-package format-all
    :ensure t)
  (add-hook 'prog-mode-hook 'format-all-mode)
  (add-hook 'format-all-mode-hook 'format-all-ensure-formatter)
format-all-ensure-formatter

Multiple Cursors

  (use-package multiple-cursors
    :straight t
    :ensure   t
    :bind (("H-SPC" . set-rectangular-region-anchor)
           ("C-M-SPC" . set-rectangular-region-anchor)
           ("C->" . mc/mark-next-like-this)
           ("C-<" . mc/mark-previous-like-this)
           ("C-c C->" . mc/mark-all-like-this)
           ("C-c C-SPC" . mc/edit-lines)
           ))

Obsidian

  ;; (use-package obsidian
  ;;   :ensure t
  ;;   :demand t
  ;;   :config
  ;;   (obsidian-specify-path "~/PersonalDocuments/Personal/TTRPG Vault")
  ;;   (global-obsidian-mode t)
  ;;   :custom
  ;;   :bind (:map obsidian-mode-map
  ;;               ("C-c C-o" . obsidian-follow-link-at-point)
  ;;               ("C-c C-b" . obsidian-backlink-jump)
  ;;               ("C-c C-l" . obsidian-insert-wikilink)))