Skip to content

Latest commit

 

History

History
3123 lines (2664 loc) · 90.4 KB

README.org

File metadata and controls

3123 lines (2664 loc) · 90.4 KB

.emacs.d

Synopsis

Emacs configuration files written with the help of org-mode and org-babel

Prelude

Install xcode cli tools

xcode-select --install

Change system maxfiles

launchctl limit maxfiles 65536 65536
cat <<EOF >/Library/LaunchDaemons/limit.maxfiles.plist
<?xml version="1.0" encoding="UTF-8"?>
DOCTYPE plist PUBLIC "-//Apple/DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Label</key>
      <string>limit.maxfiles</string>
    <key>ProgramArguments</key>
      <array>
        <string>launchctl</string>
        <string>limit</string>
        <string>maxfiles</string>
        <string>65536</string>
        <string>65536</string>
      </array>
    <key>RunAtLoad</key>
      <true />
  </dict>
</plist>
EOF

Install Emacs with homebrew

brew tap jimeh/emacs-builds
brew install emacs-app-good

# Disable font smoothing
defaults write $(osascript -e 'id of app "Emacs"') AppleFontSmoothing -int 0
defaults write NSGlobalDomain KeyRepeat -int 0.02

defaults write com.apple.dock autohide -bool true
defaults write com.apple.dock autohide-time-modifier -float 0.5
killall Dock

chflags nohidden ~/Library

defaults write com.apple.screencapture disable-shadow -bool true

Enable lexical binding

;;; -*- lexical-binding: t -*-
(message "This is tangled README.el. lexical-binding has the value %S" lexical-binding)

auto-minor-mode (link)

(use-package auto-minor-mode)

Configuring the build-ins and bare minimum defaults

better-defaults (link)

Fixing weird quirks and poor defaults

(use-package better-defaults
  :demand t
  :config
  (ido-mode 0))

EasyGP Assistant

(defun my/epa-config ()
  (setopt epa-file-encrypt-to "[email protected]")
  (setopt password-cache-expiry (* 60 15))
  (setopt epa-file-select-keys t)
  (setopt epg-pinentry-mode 'loopback)
  (fset 'epg-wait-for-status 'ignore))

(use-package epa
  :if (eq system-type 'darwin)
  :ensure nil
  :ensure-system-package pinentry-mac
  :config
  (my/epa-config))

(use-package epa
  :if (eq system-type 'gnu/linux)
  :ensure nil
  :config
  (my/epa-config))

when starting, we should prepare our gpg config

gpg --list-keys
echo "pinentry-program /opt/homebrew/bin/pinentry-mac" >> $HOME/.gnupg/gpg-agent.conf
gpg --expert --full-generate-key

https://alexschroeder.ch/wiki/2016-03-17_GPG_Agent_and_Emacs

auth-source

Providing user credentials from encrypted file

(use-package auth-source
  :ensure nil
  :no-require t
  :custom
  (auth-sources '("~/.authinfo.gpg")))

async (link)

(use-package async
  :config
  (dired-async-mode 1))

which-key

(use-package which-key
  :init
  (which-key-mode)
  :config
  (add-to-list 'which-key-replacement-alist '(("TAB" . nil) . ("" . nil)))
  (add-to-list 'which-key-replacement-alist '(("RET" . nil) . ("" . nil)))
  (add-to-list 'which-key-replacement-alist '(("DEL" . nil) . ("" . nil)))
  (add-to-list 'which-key-replacement-alist '(("SPC" . nil) . ("" . nil)))
  :custom
  ((which-key-sort-order #'which-key-prefix-then-key-order)
   (which-key-add-column-padding 1)
   (which-key-min-display-lines 6)
   (which-key-side-window-location 'bottom)
   (which-key-side-window-max-height 0.25)
   (which-key-side-window-max-width 0.33)
   (which-key-popup-type 'side-window)
   (which-key-sort-uppercase-first nil)))

server-start

Start emacs server if you run just the app. This can help with startup of other emacsclients instances

(if (and (fboundp 'server-running-p)
         (not (server-running-p)))
   (server-start))

Setting default display and editing options

(use-package shell
  :ensure nil
  :hook
  (shell-mode . ansi-color-for-comint-mode-on))

(use-package emacs
  :ensure nil
  :custom
  (apropos-do-all t)
  (auto-save-default nil)
  (completion-ignore-case t)
  (create-lockfiles nil)
  (cursor-in-non-selected-windows nil)
  (debugger-stack-frame-as-list t)
  (dired-kill-when-opening-new-dired-buffer t)
  (ffap-machine-p-known 'reject)
  (frame-resize-pixelwise t)
  (frame-title-format nil)
  (global-auto-revert-non-file-buffers t)
  (highlight-nonselected-windows nil)
  (history-delete-duplicates t)
  (indent-tabs-mode nil)
  (inhibit-compacting-font-caches t)
  (inhibit-startup-echo-area-message user-login-name)
  (inhibit-startup-message t)
  (inhibit-startup-screen t)
  (make-backup-files nil)
  (minibuffer-prompt-properties '(read-only t point-entered minibuffer-avoid-prompt face minibuffer-prompt))
  (narrow-to-defun-include-comments t)
  (ns-right-alternate-modifier nil)
  (ns-use-proxy-icon nil)
  (pop-up-frames nil)
  (read-buffer-completion-ignore-case t)
  (ring-bell-function 'ignore)
  (scroll-margin 0)
  (scroll-preserve-screen-position t)
  (scroll-step 1)
  (show-trailing-whitespace nil)
  (switch-to-buffer-in-dedicated-window nil)
  (switch-to-buffer-obey-display-actions t)
  (transient-mark-mode t)
  (use-dialog-box nil)
  (vc-handled-backends nil)
  (visible-bell t)
  (x-stretch-cursor t)
  (undo-limit         50000000)
  (undo-strong-limit 100000000)
  (undo-outer-limit  300000000)
  (switch-to-prev-buffer-skip t)
  (text-mode-ispell-word-completion nil)
  (remote-file-name-inhibit-cache nil)
  (async-shell-command-buffer 'new-buffer)
  (tramp-verbose 1)
  (vc-ignore-dir-regexp
   (format "%s\\|%s"
           vc-ignore-dir-regexp
           tramp-file-name-regexp))
  :config
  (prefer-coding-system 'utf-8)
  (set-default 'truncate-lines t)
  (global-hl-line-mode 0)
  (set-window-margins nil 0 0)
  (electric-pair-mode 0)
  (line-number-mode 0)
  (column-number-mode 0)
  (delete-selection-mode 1)
  (global-auto-revert-mode 1)
  (menu-bar-mode 0)
  (save-place-mode 1)
  (recentf-mode 1)
  (global-so-long-mode 1)
  (setq-default bidi-display-reordering 'left-to-right
                bidi-paragraph-direction 'left-to-right
                bidi-inhibit-bpa t)

  (add-hook 'after-save-hook 'executable-make-buffer-file-executable-if-script-p)

  (advice-add #'tty-run-terminal-initialization :override #'ignore)
  (advice-add #'display-startup-echo-area-message :override #'ignore)

  (when (eq system-type 'darwin)
    (defvar ls-lisp-use-insert-directory-program)
    (setq ns-use-srgb-colorspace t)
    (require 'ls-lisp)
    (setq ls-lisp-use-insert-directory-program nil))
  (fset 'yes-or-no-p 'y-or-n-p))

(use-package prog-mode
  :ensure nil
  :hook (prog-mode . electric-pair-mode))

;; http://mbork.pl/2021-11-13_y-or-n-p_but_with_RET_meaning_yes
(defconst y-or-n-p-ret-yes-map
  (let ((map (make-sparse-keymap)))
    (set-keymap-parent map y-or-n-p-map)
    (define-key map [return] 'act)
    map)
  "A keymap for y-or-n-p with RET meaning \"yes\".")

(setq y-or-n-p-map y-or-n-p-ret-yes-map)

(global-unset-key (kbd "C-x C-c"))
(global-unset-key (kbd "s-w"))
(global-unset-key (kbd "C-x C-z"))
(global-unset-key (kbd "C-<wheel-up>"))
(global-unset-key (kbd "C-<wheel-down>"))
(global-unset-key (kbd "<mouse-2>"))
(global-unset-key (kbd "s-t"))

;; font sizes
(defun my/increase-font-size ()
  (interactive)
  (let ((old-face-attribute (face-attribute 'default :height)))
    (message (format "Changed font size to %d" (+ old-face-attribute 10)))
    (set-face-attribute 'default nil :height (+ old-face-attribute 10))))

(defun my/decrease-font-size ()
  (interactive)
  (let ((old-face-attribute (face-attribute 'default :height)))
    (message (format "Changed font size to %d" (- old-face-attribute 10)))
    (set-face-attribute 'default nil :height (- old-face-attribute 10))))

;; TODO: find better replacement for those bindigns
(global-set-key (kbd "<pinch>") 'ignore)
(global-set-key (kbd "<C-wheel-up>") 'ignore)
(global-set-key (kbd "<C-wheel-down>") 'ignore)

(global-set-key (kbd "s-=") 'my/increase-font-size)
(global-set-key (kbd "s--") 'my/decrease-font-size)
(global-set-key (kbd "C-l") 'goto-line)
(global-set-key (kbd "<escape>") 'keyboard-escape-quit)
(global-set-key (kbd "M-s-<right>") 'tab-next)
(global-set-key (kbd "M-s-<left>") 'tab-previous)

Comint

(use-package comint
  :ensure nil
  :config
  (add-to-list 'comint-output-filter-functions 'ansi-color-process-output))

Compilation

(use-package compile
  :ensure nil
  :custom
  (compilation-scroll-output t)
  (compilation-auto-jump-to-first-error t)
  (compilation-max-output-line-length nil)
  (compilation-ask-about-save nil)
  (compilation-environment '("TERM=xterm-256color")))

Auto-compile

(use-package auto-compile
  :custom
  (auto-compile-display-buffer nil)
  (auto-compile-mode-line-counter t)
  :config
  (auto-compile-on-load-mode)
  (auto-compile-on-save-mode))

xwidget-webkit problem with emacsclient

We need to redefine xwidget-webkit-enable-plugins variable for webkit to work properly

(if (boundp 'xwidget-webkit-enable-plugins)
      (setq xwidget-webkit-enable-plugins t)
  (defvar xwidget-webkit-enable-plugins t))

Default trash behavior

(use-package osx-trash
  :if (eq system-type 'darwin)
  :defer 2
  :custom
  (osx-trash-setup)
  (osx-trash-command "trash -F")
  (delete-by-moving-to-trash t))

Disabling suspend-frame binding

Very annoying binding, lets get rid of it.

(global-unset-key (kbd "C-z"))

Hardtimes

(use-package hardtime
  :ensure (hardtime :fetcher github :repo "ichernyshovvv/hardtime.el")
  :config
  (hardtime-mode))

Inhibit mouse

Disable all mouse input

(use-package inhibit-mouse
  :ensure (inhibit-mouse :fetcher github :repo "jamescherti/inhibit-mouse.el")
  :config
  (inhibit-mouse-mode))

Browser Url

(use-package browse-url
  :ensure nil
  :custom
  (browse-url-browser-function 'browse-url-default-browser))

Re-builder

(use-package re-builder
  :ensure nil
  :custom
  (reb-re-syntax 'string))

Themes, Fonts, Colors

Load theme

(use-package catppuccin-theme
  :demand t
  :preface
  (defun my/set-font (frame)
    (set-face-attribute 'default frame :font "JetBrains Mono" :weight 'normal :height 160))
  :hook (after-make-frame-functions . my/set-font)
  :custom-face
  (show-paren-match ((t (:foreground "#181825" :inherit 'match))))
  :config
  (load-theme 'catppuccin t)
  (when (and (eq system-type 'darwin))
    (system-packages-install "font-jetbrains-mono"))
  (when (and (eq system-type 'gnu/linux)
             (not (file-exists-p "~/.local/share/fonts/fonts/webfonts/JetBrainsMono-Light.woff2")))
    (shell-command "/bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/JetBrains/JetBrainsMono/master/install_manual.sh)\""))
  (my/set-font nil))

Nerd Icons

(use-package nerd-icons
  :defines nerd-icons-regexp-icon-alist
  :custom
  (nerd-icons-color-icons t)
  :config
  (add-to-list 'nerd-icons-regexp-icon-alist
    '("_?test\\.rb$"        nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-red))
  (add-to-list 'nerd-icons-regexp-icon-alist
    '("_?test_helper\\.rb$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-dred))
  (add-to-list 'nerd-icons-regexp-icon-alist
    '("_?spec\\.rb$"        nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-red))
  (add-to-list 'nerd-icons-regexp-icon-alist
    '("_?spec_helper\\.rb$" nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-dred))
  (add-to-list 'nerd-icons-regexp-icon-alist
    '("-?spec\\.ts$"        nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-blue))
  (add-to-list 'nerd-icons-regexp-icon-alist
    '("-?test\\.ts$"        nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-blue))
  (add-to-list 'nerd-icons-regexp-icon-alist
    '("-?spec\\.js$"        nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-lpurple))
  (add-to-list 'nerd-icons-regexp-icon-alist
    '("-?test\\.js$"        nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-lpurple))
  (add-to-list 'nerd-icons-regexp-icon-alist
    '("-?spec\\.jsx$"       nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-blue-alt))
  (add-to-list 'nerd-icons-regexp-icon-alist
    '("-?test\\.jsx$"       nerd-icons-mdicon "nf-md-test_tube" :face nerd-icons-blue-alt)))

(use-package nerd-icons-dired
  :hook (dired-mode . nerd-icons-dired-mode))

(use-package nerd-icons-ibuffer
  :hook (ibuffer-mode . nerd-icons-ibuffer-mode))

(use-package nerd-icons-completion
  :after corfu marginalia
  :functions (nerd-icons-completion-mode nerd-icons-completion-marginalia-setup)
  :config
  (nerd-icons-completion-mode)
  (add-hook 'marginalia-mode-hook #'nerd-icons-completion-marginalia-setup))

(use-package nerd-icons-corfu
  :after corfu
  :commands nerd-icons-corfu-formatter
  :config
  (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter))

Ligatures

;; This assumes you've installed the package via MELPA.
(use-package ligature
  :functions ligature-set-ligatures global-ligature-mode
  :config
  (ligature-set-ligatures
   '(js-base-mode typescript-mode typescript-ts-mode)
   '("?." "?=" "<>"
     "</>" "/>" "<!--" "<#--" "-->" "=>"
     "..." ".."
     "//" "///"))

  (ligature-set-ligatures
   '(emacs-lisp-mode lisp-data-mode)
   '(";;;" ";;"))

  (ligature-set-ligatures
   'go-mode
   '(":="))

  (ligature-set-ligatures
   'prog-mode
   '("--" "==" "===" "!=" "!==" "&&" "=/=" "++" "#!" "<=" ">=" "||" "|>" "<|" "..." ".."))

   ;; (ligature-set-ligatures
   ;;  t
   ;;  '("--" "---"
   ;;    "=:=" "&&&" "&="  "+++" "***" ";;" "!!"
   ;;    "??" "???" "?:" "?." "?=" "<:" ":<" ":>" ">:" "<:<" "<>" "<<<" ">>>"
   ;;    "<<" ">>" "-|" "_|_" "|-" "||-" "|=" "||=" "##" "###" "####"
   ;;    "#{" "#[" "]#" "#(" "#?" "#_" "#_(" "#:" "#!" "#=" "^=" "<$>" "<$"
   ;;    "$>" "<+>" "<+" "+>" "<*>" "<*" "*>" "</" "</>" "/>" "<!--" "<#--"
   ;;    "-->" "->" "->>" "<<-" "<-" "<=<" "=<<" "<<=" "<==" "<=>" "<==>"
   ;;    "==>" "=>" "=>>" ">=>" ">>=" ">>-" ">-" "-<" "-<<" ">->" "<-<" "<-|"
   ;;    "<=|" "|=>" "|->" "<->" "<~~" "<~" "<~>" "~~" "~~>" "~>" "~-" "-~"
   ;;    "~@" "[||]" "|]" "[|" "|}" "{|" "[<" ">]" "||>" "<||"
   ;;    "|||>" "<|||" "<|>" ".=" "..<" ".?" "::" ":::" "::="
   ;;    ":?" ":?>" "//" "///" "/=" "//=" "/==" "@_" "__" "???"
   ;;    "<:<" ";;;"))
   (global-ligature-mode t))

Buffers, Windows, Frames and scrolling

(setopt jit-lock-defer-time 0)
(setopt fast-but-imprecise-scrolling t)

Focus new frame

(when (featurep 'ns)
  (defun ns-raise-emacs ()
    "Raise Emacs."
    (ns-do-applescript "tell application \"Emacs\" to activate"))

  (defun ns-raise-emacs-with-frame (frame)
    "Raise Emacs and select the provided frame."
    (with-selected-frame frame
      (when (display-graphic-p)
        (ns-raise-emacs))))

  (add-hook 'after-make-frame-functions 'ns-raise-emacs-with-frame)
  (when (display-graphic-p)
    (ns-raise-emacs)))

Posframe

(use-package posframe
  :demand t)

pooper (link)

(use-package popper
  :ensure t ; or :straight t
  :bind (("s-§"          . popper-toggle-latest)
         ("M-§"          . popper-cycle)
         ("s-M-§"        . popper-toggle-type)
         ("s-<escape>"   . popper-toggle-latest)
         ("M-<escape>"   . popper-cycle)
         ("C-M-<escape>" . popper-toggle-type))
  :custom
  (popper-reference-buffers
   '("\\*Messages\\*"
     "Output\\*$"
     "\\*Async Shell Command\\*"
     compilation-mode
     vterm-mode
     "\\*verminal"))
  (popper-mode-line '(:eval
                      (propertize " POP " 'face 'mode-line-emphasis)))
  (popper-display-control t)
  (popper-group-function nil)
  :config
  (popper-mode +1)
  (popper-echo-mode +1))

tab-bar

(use-package tab-bar
  :ensure nil
  :custom
  ;; Do not show buttons.
  (tab-bar-new-button-show t)
  (tab-bar-close-button-show t)
  (tab-bar-tab-hints t))

tab-line

(use-package tab-line
  :ensure nil
  :custom
  (tab-line-separator " | ")
  (tab-line-close-button-show nil)
  (tab-line-new-button-show nil))

transient

(use-package transient)

transient-posframe

(use-package transient-posframe
  :after transient
  :ensure (transient-posframe :fetcher github :repo "tarsiiformes/transient-posframe" :branch "fix-sizing")
  ;; :ensure (transient-posframe :fetcher github :repo "yanghaoxie/transient-posframe")
  :config
  (transient-posframe-mode))

use-package-transient

(use-package use-package-transient
  :ensure (use-package-transient :fetcher git :url "https://codeberg.org/Thaodan/use-package-transient.git"))

bufler

(use-package bufler
  :bind
  ("C-x C-b" . bufler-list)
  :custom
  (bufler-workspace-switch-buffer-sets-workspace t))

framemove

(use-package framemove
  :ensure (framemove :fetcher github :host github :repo "emacsmirror/framemove")
  :custom
  (framemove-hook-into-windmove t)
  :config
  (windmove-default-keybindings 'super)
  (windmove-swap-states-default-keybindings (list 'super 'control))
  (winner-mode 1))

perfect-margin

(use-package perfect-margin
  :custom
  (perfect-margin-visible-width 128)
  :config
  (perfect-margin-mode nil)
  (setq perfect-margin-ignore-regexps '("^minibuf" "^[[:space:]]\\*"))
  (dolist (margin '("<left-margin> " "<right-margin> "))
    (global-set-key (kbd (concat margin "<mouse-1>")) 'ignore)
    (global-set-key (kbd (concat margin "<mouse-3>")) 'ignore)))

ultra-scrol

(use-package ultra-scroll
  :ensure (ultra-scroll :fetcher github :repo "jdtsmith/ultra-scroll")
  :custom
  (scroll-conservatively 101)
  (scroll-margin 0)
  :config
  (ultra-scroll-mode 1))

Editing

;; Sometimes i press kill-region when transient mark mode is not
;; active, This should prevent that.
(setq mark-even-if-inactive nil)

eval-sexp-fu

(use-package eval-sexp-fu
  :config
  (require 'eval-sexp-fu))

litable

(use-package litable
  :hook (emacs-lisp-mode . litable-mode))

meow

(use-package meow
  :preface
  (defun meow-setup ()
    (setq meow-cheatsheet-layout meow-cheatsheet-layout-qwerty)
    (meow-motion-overwrite-define-key
     '("j" . meow-next)
     '("k" . meow-prev)
     '("<escape>" . ignore))
    (meow-leader-define-key
     ;; SPC j/k will run the original command in MOTION state.
     '("j" . "H-j")
     '("k" . "H-k")
     ;; Use SPC (0-9) for digit arguments.
     '("1" . meow-digit-argument)
     '("2" . meow-digit-argument)
     '("3" . meow-digit-argument)
     '("4" . meow-digit-argument)
     '("5" . meow-digit-argument)
     '("6" . meow-digit-argument)
     '("7" . meow-digit-argument)
     '("8" . meow-digit-argument)
     '("9" . meow-digit-argument)
     '("0" . meow-digit-argument)
     '("/" . meow-keypad-describe-key)
     '("?" . meow-cheatsheet))
    (meow-normal-define-key
     '("0" . meow-expand-0)
     '("9" . meow-expand-9)
     '("8" . meow-expand-8)
     '("7" . meow-expand-7)
     '("6" . meow-expand-6)
     '("5" . meow-expand-5)
     '("4" . meow-expand-4)
     '("3" . meow-expand-3)
     '("2" . meow-expand-2)
     '("1" . meow-expand-1)
     '("-" . negative-argument)
     '(";" . meow-reverse)
     '("," . meow-inner-of-thing)
     '("." . meow-bounds-of-thing)
     '("[" . meow-beginning-of-thing)
     '("]" . meow-end-of-thing)
     '("a" . meow-append)
     '("A" . meow-open-below)
     '("b" . meow-back-word)
     '("B" . meow-back-symbol)
     '("c" . meow-change)
     '("d" . meow-delete)
     '("D" . meow-backward-delete)
     '("e" . meow-next-word)
     '("E" . meow-next-symbol)
     '("f" . meow-find)
     '("g" . meow-cancel-selection)
     '("G" . meow-grab)
     '("h" . meow-left)
     '("H" . meow-left-expand)
     '("i" . meow-insert)
     '("I" . meow-open-above)
     '("j" . meow-next)
     '("J" . meow-next-expand)
     '("k" . meow-prev)
     '("K" . meow-prev-expand)
     '("l" . meow-right)
     '("L" . meow-right-expand)
     '("m" . meow-join)
     '("n" . meow-search)
     '("o" . meow-block)
     '("O" . meow-to-block)
     '("p" . meow-yank)
     '("q" . meow-quit)
     '("Q" . meow-goto-line)
     '("r" . meow-replace)
     '("R" . meow-swap-grab)
     '("s" . meow-kill)
     '("t" . meow-till)
     '("u" . meow-undo)
     '("U" . meow-undo-in-selection)
     '("v" . meow-visit)
     '("w" . meow-mark-word)
     '("W" . meow-mark-symbol)
     '("x" . meow-line)
     '("X" . meow-goto-line)
     '("y" . meow-save)
     '("Y" . meow-sync-grab)
     '("z" . meow-pop-selection)
     '("'" . repeat)
     '("<escape>" . ignore))))

Expand region

(use-package expreg
  :ensure t
  :bind
  ("C-=" . expreg-expand)
  ("C--" . expreg-contract))

Move lines using alt + arrows

(use-package move-text
  :config
  (move-text-default-bindings))

multiple-cursors (link)

Multiple cursors for Emacs. This is some pretty crazy functionality, so yes, there are kinks. Don’t be afraid tho, I’ve been using it since 2011 with great success and much merriment.

(use-package multiple-cursors
  :defer 0.5
  :hook
  (multiple-cursors-mode
   .
   (lambda ()
     (if multiple-cursors-mode
         (progn
           (message "multiple cursor on")
           (corfu-mode 0))
       (progn
         (message "multiple cursor off")
         (corfu-mode 1)))))
  :bind
  ("C->" . mc/mark-next-like-this)
  ("C-<" . mc/mark-previous-like-this))

Cycling between different var notations

(use-package string-inflection
  :bind
  ("C-c C-u" . string-inflection-all-cycle))

Flyspell

(use-package ispell
  :if (executable-find "aspell")
  :ensure nil
  :defer t
  :config
  (add-to-list 'ispell-skip-region-alist '(":\\(PROPERTIES\\|LOGBOOK\\):" . ":END:"))
  (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_SRC" . "#\\+END_SRC"))
  (add-to-list 'ispell-skip-region-alist '("#\\+BEGIN_EXAMPLE" . "#\\+END_EXAMPLE"))

  (setq ispell-program-name "aspell"
        ispell-extra-args   '("--sug-mode=ultra" "--run-together")
        ispell-aspell-dict-dir (ispell-get-aspell-config-value "dict-dir")
        ispell-aspell-data-dir (ispell-get-aspell-config-value "data-dir")
        ispell-personal-dictionary (expand-file-name (concat "ispell/" ispell-dictionary ".pws")
                                                     user-emacs-directory)))

(use-package flyspell
  :after ispell
  :ensure nil
  :defer t
  :config
  (setq flyspell-issue-welcome-flag nil
        flyspell-issue-message-flag nil))

(use-package flyspell-correct
  :defer t
  :bind
  (([remap ispell-word] . flyspell-correct-at-point)
   (:map flyspell-mode-map
         ("C-;" . flyspell-correct-wrapper))))

(use-package flyspell-correct-popup
  :after flyspell-correct)

(use-package flyspell-lazy
  :defer t
  :after flyspell
  :config
  (setq flyspell-lazy-idle-seconds 1
        flyspell-lazy-window-idle-seconds 3)
  (flyspell-lazy-mode +1))

unfill

(use-package unfill
  :bind ([remap fill-paragraph] . unfill-toggle))

visual-regexp-steroids

(use-package pcre2el)

(use-package visual-regexp
  :after pcre2el
  :custom
  (vr/engine 'pcre2el)
  :bind
  ("C-c r" . vr/replace)
  ("C-c q" . vr/query-replace)
  ("C-c m" . vr/mc-mark)
  ("C-r" . vr/isearch-backward)
  ("C-s" . vr/isearch-forward))

(use-package visual-regexp-steroids
  :after visual-regexp)

List filtering helpers

Vertico (link)

Some of the config is borrowed straight from Kristoffer Balintonas blog post from

(defun my/vertico-multiform-flat-toggle ()
  "Toggle between flat and reverse."
  (interactive)
  (vertico-multiform--display-toggle 'vertico-flat-mode)
  (if vertico-flat-mode
      (vertico-multiform--temporary-mode 'vertico-reverse-mode -1)
    (vertico-multiform--temporary-mode 'vertico-reverse-mode 1)))

(defun my/vertico-quick-embark (&optional arg)
  "Embark on candidate using quick keys."
  (interactive)
  (when (vertico-quick-jump)
    (embark-act arg)))

(use-package vertico
  :demand t
  :hook ((rfn-eshadow-update-overlay . vertico-directory-tidy)
         (minibuffer-setup . vertico-repeat-save))
  :bind (:map vertico-map
              ("<tab>" . vertico-insert)
              ("<escape>" . minibuffer-keyboard-quit)
              ("?" . minibuffer-completion-help)
              ("C-M-n" . vertico-next-group)
              ("C-M-p" . vertico-previous-group)
              ("M-o" . my/vertico-quick-embark)
              ("C-l" . my/vertico-multiform-flat-toggle)
              ("C-i" . vertico-quick-insert)
              ("C-o" . vertico-quick-exit)
              ("M-G" . vertico-multiform-grid)
              ("M-F" . vertico-multiform-flat)
              ("M-R" . vertico-multiform-reverse)
              ("M-U" . vertico-multiform-unobtrusive)
              ("<backspace>" . vertico-directory-delete-char)
              ("C-w" . vertico-directory-delete-word)
              ("C-<backspace>" . vertico-directory-delete-word)
              ("RET" . vertico-directory-enter))

  :custom
  (vertico-resize nil)
  (vertico-cycle t)
  (vertico-grid-separator "        ")
  (vertico-grid-lookahead 50)
  (vertico-buffer-display-action '(display-buffer-reuse-window))
  (vertico-sort-function 'vertico-sort-history-alpha)
  (vertico-multiform-categories
   '((consult-line
      posframe
      (vertico-posframe-poshandler . posframe-poshandler-frame-top-center)
      (vertico-posframe-border-width . 10)
      (vertico-posframe-fallback-mode . vertico-buffer-mode))
     (consult-grep buffer)
     (consult-ripgrep buffer)
     (consult-buffer reverse indexed)
     (imenu buffer)
     (library indexed)
     (org-roam-node posframe indexed)
     (t posframe)))
  (vertico-multiform-commands
   '((consult-imenu
      posframe
      (vertico-sort-function . nil))
     (consult-line
      posframe
      (vertico-posframe-poshandler . posframe-poshandler-frame-top-center)
      (vertico-posframe-border-width . 10)
      ;; NOTE: This is useful when emacs is used in both in X and
      ;; terminal, for posframe do not work well in terminal, so
      ;; vertico-buffer-mode will be used as fallback at the
      ;; moment.
      (vertico-posframe-fallback-mode . vertico-buffer-mode))
     (t posframe)))
  :config
  (vertico-mode 1)
  (vertico-multiform-mode 1)

  ;; https://github.com/robbert-vdh/dotfiles/blob/master/modules/emacs/doom/config.org#vertico
  (define-advice marginalia--buffer-file (:around (fn &rest args) my/marginalia--buffer-file)
    (let ((buffer-path (apply fn args)))
      (if (and (not (string-empty-p buffer-path)) (file-exists-p buffer-path))
          (if-let* ((absolute-root (marginalia--project-root))
                    (project-root (abbreviate-file-name absolute-root))
                    (is-prefix (string-prefix-p project-root buffer-path)))
              (string-remove-prefix project-root buffer-path)
            (shrink-path-file buffer-path))
        buffer-path))))

(use-package vertico-posframe
  :after vertico
  :custom
  (vertico-posframe-parameters
   '((left-fringe . 8)
     (right-fringe . 8))))

also helpful emacs config just for vertico

(use-package emacs
  :ensure nil
  :bind
  ("s-," . (lambda () (interactive)
             (find-file (concat user-emacs-directory "README.org"))))
  :init
  (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)

  :custom
  ;; Do not allow the cursor in the minibuffer prompt
  (minibuffer-prompt-properties
   '(read-only t cursor-intangible t face minibuffer-prompt))
  ;; Emacs 28: Hide commands in M-x which do not work in the current mode.
  ;; Vertico commands are hidden in normal buffers.
  (read-extended-command-predicate
        #'command-completion-default-include-p)
  ;; Enable recursive minibuffers
  (enable-recursive-minibuffers t))
(use-package recursion-indicator
  :demand t
  :config
  (recursion-indicator-mode))

Marginalia

;; Enable richer annotations using the Marginalia package
(use-package marginalia
  :demand t
  :bind (:map minibuffer-local-map
         ("M-A" . marginalia-cycle))
  :custom
  ;; (marginalia-max-relative-age)
  (marginalia-align 'right)
  :config
  (marginalia-mode))

Orderless (link)

(use-package orderless
  :defer 0.5
  :init
  (setq completion-styles '(orderless basic)
        completion-category-defaults nil
        completion-category-overrides '((file (styles partial-completion)))))

Savehist

(use-package savehist
  :ensure nil
  :defer t
  :after no-littering
  :custom
  (history-length 100)
  :config
  (savehist-mode 1)
  (add-to-list 'savehist-additional-variables 'corfu-history))

Consult (link)

;; Example configuration for Consult
(use-package consult
  :defer 0.5
  ;; Replace bindings. Lazily loaded due by `use-package'.
  :bind (;; C-c bindings (mode-specific-map)
         ("C-c h" . consult-history)
         ("C-c m" . consult-mode-command)
         ("C-c b" . consult-bookmark)
         ("C-c k" . consult-kmacro)
         ;; C-x bindings (ctl-x-map)
         ("C-x M-:" . consult-complex-command)     ;; orig. repeat-complex-command
         ("C-x b" . consult-buffer)                ;; orig. switch-to-buffer
         ("C-x 4 b" . consult-buffer-other-window) ;; orig. switch-to-buffer-other-window
         ("C-x 5 b" . consult-buffer-other-frame)  ;; orig. switch-to-buffer-other-frame
         ;; Custom M-# bindings for fast register access
         ("M-#" . consult-register-load)
         ("M-'" . consult-register-store)          ;; orig. abbrev-prefix-mark (unrelated)
         ("C-M-#" . consult-register)
         ;; Other custom bindings
         ("M-y" . consult-yank-pop)                ;; orig. yank-pop
         ("<help> a" . consult-apropos)            ;; orig. apropos-command
         ;; M-g bindings (goto-map)
         ("M-g e" . consult-compile-error)
         ("M-g f" . consult-flymake)               ;; Alternative: consult-flycheck
         ("M-g g" . consult-goto-line)             ;; orig. goto-line
         ("M-g M-g" . consult-goto-line)           ;; orig. goto-line
         ("M-g o" . consult-outline)               ;; Alternative: consult-org-heading
         ("M-g m" . consult-mark)
         ("M-g k" . consult-global-mark)
         ("M-g i" . consult-imenu)
         ("M-g I" . consult-imenu-multi)
         ;; M-s bindings (search-map)
         ("M-s f" . consult-find)
         ("M-s F" . consult-locate)
         ("M-s g" . consult-grep)
         ("M-s G" . consult-git-grep)
         ("M-s r" . consult-ripgrep)
         ("M-s l" . consult-line)
         ("M-s L" . consult-line-multi)
         ("M-s m" . consult-multi-occur)
         ("M-s k" . consult-keep-lines)
         ("M-s u" . consult-focus-lines)
         ;; Isearch integration
         ("M-s e" . consult-isearch-history)
         :map isearch-mode-map
         ("M-e" . consult-isearch-history)         ;; orig. isearch-edit-string
         ("M-s e" . consult-isearch-history)       ;; orig. isearch-edit-string
         ("M-s l" . consult-line)                  ;; needed by consult-line to detect isearch
         ("M-s L" . consult-line-multi))           ;; needed by consult-line to detect isearch

  ;; Enable automatic preview at point in the *Completions* buffer.
  ;; This is relevant when you use the default completion UI,
  ;; and not necessary for Vertico, Selectrum, etc.

  ;; The :init configuration is always executed (Not lazy)
  :init

  ;; Optionally configure the register formatting. This improves the register
  ;; preview for `consult-register', `consult-register-load',
  ;; `consult-register-store' and the Emacs built-ins.
  (setq register-preview-delay 0.5
        register-preview-function #'sconsult-register-format)

  ;; Optionally tweak the register preview window.
  ;; This adds thin lines, sorting and hides the mode line of the window.
  (advice-add #'register-preview :override #'consult-register-window)

  ;; Use Consult to select xref locations with preview
  (setq xref-show-xrefs-function #'consult-xref
        xref-show-definitions-function #'consult-xref)

  :config
  (setq consult-preview-key "M-.")
  (setq consult-narrow-key "<") ;; (kbd "C-+")

  (autoload 'projectile-project-root "projectile")
  (setq consult-project-root-function #'projectile-project-root)

  (defun consult-info-emacs ()
    "Search through Emacs info pages."
    (interactive)``
    (consult-info "emacs" "efaq" "elisp" "cl" "compat")))

Consult Projectile (link)

(use-package consult-projectile
  :bind-keymap ("C-c p" . projectile-command-map)
  :bind (:map projectile-command-map
              ("p" . consult-projectile))
  :custom
  (projectile-switch-project-action 'consult-projectile))

Consult flycheck (link)

(use-package consult-flycheck
  :after (consult flycheck))

Consult Dir (link)

(use-package consult-dir
  :ensure t
  :bind (("C-x C-d" . consult-dir)
         :map vertico-map
         ("C-x C-d" . consult-dir)
         ("C-x C-j" . consult-dir-jump-file)))

Terminals, Shells

Eshell (link)

Eshell is a shell written entirely in Emacs-Lisp, and it replicates most of the features and commands from GNU CoreUtils and the Bourne-like shells. So by re-writing common commands like ls and cp in Emacs-Lisp, Eshell will function identically on any environment Emacs itself runs on.

PS. some config stolen from https://github.com/gopar/.emacs.d

(use-package eshell
  :after (corfu cape pcmpl-args)
  :demand t
  :ensure nil
  :functions (eshell-previous-matching-input-from-input eshell-next-matching-input-from-input)
  :defines (eshell-mode-map eshell-hist-mode-map)
  :custom
  (eshell-banner-message "")
  (eshell-error-if-no-glob t)
  (eshell-hist-ignoredups t)
  (eshell-history-size 1024)
  (eshell-input-filter 'my/eshell-input-filter)
  (eshell-last-dir-ring-size 32)
  (eshell-last-dir-unique t)
  (eshell-pushd-dunique t)
  (eshell-scroll-to-bottom-on-input t)
  (eshell-visual-commands nil)
  :preface
  (defun my/eshell-corfu-setup ()
    "Setup completion for EShell with ‘corfu’ and ‘cape’."
    (setq-local
     corfu-auto nil
     corfu-quit-at-boundary t
     corfu-quit-no-match t
     corfu-separatvor nil
     completion-at-point-functions (list #'pcomplete-completions-at-point #'cape-file)))

  (defun my/eshell-input-filter (input)
    "Do not save on the following:
       - empty lines
       - commands that start with a space, `ls`/`l`/`lsd`"
    (and
     (eshell-input-filter-default input)
     (eshell-input-filter-initial-space input)
     (not (string-prefix-p "ls " input))
     (not (string-prefix-p "lsd " input)
          (not (string-prefix-p "l " input)))))

  (defun my\corfu-send-shell (&rest _)
    "Send completion candidate when inside comint/eshell."
    (cond
     ((and (derived-mode-p 'eshell-mode) (fboundp 'eshell-send-input))
      (eshell-send-input))
     ((and (derived-mode-p 'comint-mode)  (fboundp 'comint-send-input))
      (comint-send-input))))

  :bind
  (:map eshell-mode-map
        ("<up>" . previous-line)
        ("<down>" . next-line)
        ("M-r" . consult-history))
  :hook
  (eshell-mode . (my/eshell-corfu-setup hide-mode-line))
  :config
  (setenv "PAGER" "cat")
  (setenv "TERM" "xterm-256color")
  (advice-add #'corfu-insert :after
              #'corfu-send-shell))

(use-package em-hist
  :after eshell
  :ensure nil
  :preface
  (defun my/adviced-eshell-add-input-to-history (orig-fun &rest r)
    "Cd to relative paths aren't that useful in history. Change to absolute paths."
    (require 'seq)
    (let* ((input (nth 0 r))
           (args (progn
                   (set-text-properties 0 (length input) nil input)
                   (split-string input))))
      (if (and (equal "cd" (nth 0 args))
               (not (seq-find (lambda (item)
                                ;; Don't rewrite "cd /ssh:" in history.
                                (string-prefix-p "/ssh:" item))
                              args))
               (not (seq-find (lambda (item)
                                ;; Don't rewrite "cd -" in history.
                                (string-equal "-" item))
                              args)))
          (apply orig-fun (list (format "cd %s"
                                        (expand-file-name (concat default-directory
                                                                  (nth 1 args))))))
        (apply orig-fun r))))
  :hook
  (eshell-hist-mode
   . (lambda ()
       (unbind-key (kbd "<up>") eshell-hist-mode-map)
       (unbind-key (kbd "<down>") eshell-hist-mode-map)
       (unbind-key (kbd "M-r") eshell-hist-mode-map)
       (define-key eshell-hist-mode-map (kbd "C-<up>")
                   'eshell-previous-matching-input-from-input)
       (define-key eshell-hist-mode-map (kbd "C-<down>")
                   'eshell-next-matching-input-from-input)))
  :config
  (advice-add #'eshell-add-input-to-history :around
              #'my/adviced-eshell-add-input-to-history))

(use-package eat
  :hook
  (eshell-load . eat-eshell-mode)
  :custom
  (eat-term-name "xterm"))

(use-package pcmpl-args
  :defer t
  :after (pcomplete))

(use-package pcmpl-homebrew
  :defer t
  :after (pcomplete))

(defun eshell/gst (&rest args)
  (magit-status (pop args) nil)
  (eshell/echo))

(defun eshell/ccat (file)
  "Like `cat' but output with Emacs syntax highlighting."
  (with-temp-buffer
    (insert-file-contents file)
    (let ((buffer-file-name file))
      (delay-mode-hooks
        (set-auto-mode)
        (if (fboundp 'font-lock-ensure)
            (font-lock-ensure)
          (with-no-warnings
            (font-lock-fontify-buffer)))))
    (buffer-string)))

(use-package shrink-path
  :after eshell
  :preface
  (defun my/eshell-set-outline-regexp ()
    (setq-local
     outline-regexp eshell-prompt-regexp))
  :hook
  (eshell-mode . my/eshell-set-outline-regexp)
  :custom
  ((eshell-prompt-regexp "^[^❯\n]* ❯ ")
   (eshell-prompt-function
    (lambda ()
      (let ((base/dir (shrink-path-prompt default-directory)))
        (concat (propertize (car base/dir)
                            'face 'font-lock-comment-face)
                (propertize (cdr base/dir)
                            'face 'font-lock-constant-face)
                (propertize "" 'face 'eshell-prompt)
                ;; needed for the input text to not have prompt face
                (propertize " " 'face 'default)))))))

Eshell Toggle (link)

Simple functionality to show/hide eshell/ansi-term (or almost any other buffer, see eshell-toggle-init-function description below) at the bottom of active window with directory of its buffer.

(use-package eshell-toggle
  :after eshell
  :demand t
  :defines eshell-toggle--toggle-buffer-p
  :commands (eshell-toggle)
  :preface
  (defvar my/eshell-close-on-exit nil
    "When non-nil, closing eshell (`exit`) also kills the window.")

  (defun my/eshell-toggle ()
    (interactive)
    (let ((buf (eshell-toggle)))
      (when (eq eshell-toggle--toggle-buffer-p t)
        (with-current-buffer buf
          (add-hook 'eshell-exit-hook #'delete-window nil t)))))
  :bind
  ("s-`" . my/eshell-toggle)
  :custom
  (eshell-toggle-name-separator " :: ")
  (eshell-toggle-find-project-root-package t))

ESUP

(use-package esup)

vterm

(use-package vterm
  :defer 1
  :custom
  (vterm-always-compile-module t))

(use-package multi-vterm
  :after vterm
  :bind (("C-c v" . multi-vterm)))

Remote work

Tramp

(use-package tramp
  :ensure nil
  :custom
  (tramp-inline-compress-start-size 1000)
  (tramp-copy-size-limit 10000)
  (vc-handled-backends '(Git))
  (tramp-default-method "scp")
  (tramp-use-ssh-controlmaster-options nil)
  (projectile--mode-line "Projectile")
  (tramp-verbose 1))

Displaying errors

Flycheck

(use-package flycheck
  :defer 1
  :preface
  ;; Got displaying flycheck errors in eldoc from here https://www.masteringemacs.org/article/seamlessly-merge-multiple-documentation-sources-eldoc
  (defun mp-flycheck-eldoc (callback &rest _ignored)
    "Print flycheck messages at point by calling CALLBACK."
    (when-let* ((flycheck-errors (and flycheck-mode (flycheck-overlay-errors-at (point)))))
      (mapc
       (lambda (err)
         (funcall callback
                  (format "%s: %s"
                          (let ((level (flycheck-error-level err)))
                            (pcase level
                              ('info (propertize "I" 'face 'flycheck-error-list-info))
                              ('error (propertize "E" 'face 'flycheck-error-list-error))
                              ('warning (propertize "W" 'face 'flycheck-error-list-warning))
                              (_ level)))
                          (flycheck-error-message err))
                  :thing (or (flycheck-error-id err)
                             (flycheck-error-group err))
                  :face 'font-lock-doc-face))
       flycheck-errors)))

  (defun my/flycheck-prefer-eldoc ()
    (add-hook 'eldoc-documentation-functions #'mp-flycheck-eldoc nil t)
    (setq eldoc-documentation-strategy 'eldoc-documentation-compose-eagerly)
    (setq flycheck-display-errors-function nil)
    (setq flycheck-help-echo-function nil))
  :hook
  (prog-mode . flycheck-mode)
  (flycheck-mode . my/flycheck-prefer-eldoc)
  ;; :custom-face
  ;; (flycheck-error ((t (:underline (:color "#e74c3c" :style wave) :background unspecified))))
  ;; (flycheck-info ((t (:underline (:color "#b6e63e" :style wave) :background unspecified))))
  :custom
  (flycheck-display-errors-delay 0)
  (flycheck-idle-change-delay 0)
  (flycheck-disabled-checkers '(emacs-lisp-checkdoc)))

Packages

command-log

(use-package command-log
  :ensure (command-log
           :fetcher github :repo "positron-solutions/command-log")
  :custom
  (command-log-mouse t)
  (command-log-text t)
  (command-log-merge-repeats t)
  (command-log-filter-commands '(self-insert-command handle-switch-frame org-self-insert-command)))

restclient

(use-package restclient
  :defer t
  :mode (("\\.http\\'" . restclient-mode))
  :bind (:map restclient-mode-map
              ("C-c C-f" . json-mode-beautify)))

jq

(use-package jq-mode
  :after (org-mode json-mode)
  :commands (jq-mode jq-interactively)
  :mode ("\\.jq$" . js-mode)
  :bind (:map json-mode-map
              ("C-c C-j" . jq-interactively))
  :config
  (org-babel-add-langs
   ((jq . t))))

LSP Mode

(defun my/corfu-setup-lsp ()
  "Use orderless completion style with lsp-capf instead of the
  default lsp-passthrough."
  (setf (alist-get 'styles (alist-get 'lsp-capf completion-category-defaults))
        '(orderless)))

(use-package lsp-mode
  :commands (lsp lsp-deferred)
  :after (corfu orderless posframe)
  :defer 0.5
  :hook
  ((lsp-mode . lsp-enable-which-key-integration)
   (lsp-completion-mode . my/corfu-setup-lsp))
  :custom
  (lsp-auto-guess-root t)
  (lsp-clients-typescript-prefer-use-project-ts-server t)
  (lsp-clients-typescript-preferences '(:includeCompletionsForModuleExports nil :generateReturnInDocTemplate nil))
  (lsp-completion-default-behaviour :insert)
  (lsp-completion-provider :none)
  (lsp-diagnostic-clean-after-change t)
  (lsp-diagnostics-modeline-scope :workspace)
  (lsp-eldoc-render-all nil)
  (lsp-enable-file-watchers t)
  (lsp-enable-indentation nil)
  (lsp-enable-snippet nil)
  (lsp-enable-on-type-formatting t)
  (lsp-signature-render-documentation t)
  (lsp-eslint-auto-fix-on-save t)
  (lsp-eslint-working-directories [(pattern "/Users/shfx/Developer/priv/*")
                                   (pattern "/Users/shfx/Developer/work/*")])
  (lsp-eslint-experimental '((seFlatConfig . t)))
  (lsp-file-watch-threshold 4000)
  (lsp-headerline-breadcrumb-enable nil)
  (lsp-inlay-hint-enable nil)
  (lsp-javascript-display-enum-member-value-hints t)
  (lsp-javascript-format-enable nil)
  (lsp-keymap-prefix "s-l")
  (lsp-lens-enable nil)
  (lsp-rust-analyzer-cargo-watch-command "clippy")
  (lsp-typescript-format-enable nil)
  (lsp-use-plists "true")
  (lsp-yaml-custom-tags ["!reference sequence"])
  (lsp-yaml-schema-store-local-db (no-littering-expand-var-file-name "./lsp/lsp-yaml-schemas.json"))
  ;; needed for toolchains that don't support `rustup component add`
  (lsp-rust-analyzer-server-command (list (substring (shell-command-to-string "rustup which --toolchain stable rust-analyzer") 0 -1)))
  :config
  (add-to-list 'warning-suppress-log-types '(lsp-mode))
  (add-to-list 'warning-suppress-types '(lsp-mode)))

;; (lsp-rust-analyzer-display-lifetime-elision-hints-enable t) ;; can be cahnged to "skip_trivial"
;; (lsp-rust-analyzer-display-chaining-hints t)
;; (lsp-rust-analyzer-display-lifetime-elision-hints-use-parameter-names t)
;; (lsp-rust-analyzer-display-closure-return-type-hints t)
;; (lsp-rust-analyzer-display-parameter-hints t)
;; (lsp-rust-analyzer-display-reborrow-hints t)
;; (lsp-inlay-hint-enable nil)

(use-package lsp-ui
  :after lsp-mode
  :hook (lsp-mode . lsp-ui-mode)
  :bind
  (:map lsp-ui-mode-map
        (([remap xref-find-definitions] . lsp-ui-peek-find-definitions)
         ([remap xref-find-references]  . lsp-ui-peek-find-references)))
  :custom
  (lsp-ui-doc-enable t)
  (lsp-ui-doc-position 'at-point)
  (lsp-ui-doc-alignment 'window)
  (lsp-ui-doc-show-with-cursor nil)
  (lsp-ui-doc-show-with-mouse t)
  (lsp-ui-doc-use-childframe t)
  (lsp-ui-doc-border "windowBackgroundColor")
  (lsp-ui-doc-include-signature t)
  (lsp-ui-doc-max-height 15)
  (lsp-ui-doc-max-width 100)
  (lsp-ui-sideline-enable nil)
  (lsp-ui-peek-always-show nil)
  (lsp-ui-sideline-show-hover nil))

(use-package lsp-tailwindcss
  :after lsp-mode
  :custom
  (lsp-tailwindcss-add-on-mode t))

Dabbrev

(use-package dabbrev
  :ensure nil
  ;; Swap M-/ and C-M-/
  :bind (("M-/" . dabbrev-completion)
         ("C-M-/" . dabbrev-expand))
  :config
  (add-to-list 'dabbrev-ignored-buffer-regexps "\\` ")
  ;; Since 29.1, use `dabbrev-ignored-buffer-regexps' on older.
  (add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode)
  (add-to-list 'dabbrev-ignored-buffer-modes 'pdf-view-mode))

ChatGPT

(defun shell-maker-welcome-message-ignore (config) "")

(use-package chatgpt-shell
  :bind
  ("C-c C-a" . chatgpt-shell-quick-insert)
  :custom
  (chatgpt-shell-openai-key (cadr (auth-source-user-and-password "chatgpt" "shfx")))
  (chatgpt-shell-welcome-function 'shell-maker-welcome-message-ignore))

Proced

(use-package proced
  :ensure nil
  :defer t
  :custom
  (proced-enable-color-flag t)
  (proced-tree-flag t))

Copilot

(use-package copilot
  :ensure (copilot :fetcher github
                   :repo "zerolfx/copilot.el"
                   :branch "main"
                   :files ("dist" "*.el"))
  :bind
  (:map copilot-completion-map (("<tab>" . copilot-accept-completion)
                                ("TAB" . copilot-accept-completion)
                                ("C-TAB" . 'copilot-accept-completion-by-word)
                                ("C-<tab>" . 'copilot-accept-completion-by-word)))
  )

Apheleia

(use-package apheleia
  :config
  (apheleia-global-mode +1)
  (setf (alist-get 'prisma-mode apheleia-mode-alist)
        '(prettier))
  (setf (alist-get 'svelte-ts-mode apheleia-mode-alist)
        '(prettier)))

Treesitter

Enables tree-sitter in all programming languages supported. Should be loaded before any language package

(use-package treesit
  :ensure nil
  :custom
  (treesit-font-lock-level 4))

(use-package treesit-auto
  :custom
  (treesit-auto-install 'prompt)
  :functions global-treesit-auto-mode
  :defines globatrel-treesit-auto-modes
  :preface
  (defun my/ts-mode-p (mode)
    (let* ((mode-name (symbol-name mode)))
      (cond
       ((string-suffix-p "ts-mode" mode-name) t)
       (t nil))))

  (defun my/bring-previous-mode-hooks ()
    (let ((mode-name (symbol-name major-mode)))
      (if (not (my/ts-mode-p major-mode))
          (warn "Current mode does not contain -ts suffix: %s" mode-name)
        (let* (
               (non-ts-mode-name      (concat (string-remove-suffix "-ts" (string-remove-suffix "-mode" mode-name)) "-mode"))
               (non-ts-mode-hook-name (concat non-ts-mode-name "-hook")))

          (if (not (intern non-ts-mode-hook-name))
              (message "There is no hook list named %s" non-ts-mode-hook-name)
            (run-hooks (intern non-ts-mode-hook-name))
            (message "Ran hook for %s" non-ts-mode-hook-name))))))

  (defun my/get-treesit-auto-modes ()
    "Extracts all available treesit auto modes"
    (unless global-treesit-auto-modes
      (error "global-treesit-auto-modes vartable does not exist, can't transfer hooks from non treesit modes"))
    (seq-filter 'my/ts-mode-p global-treesit-auto-modes))

  :config

  (add-to-list 'treesit-auto-langs 'svelte)

  (add-to-list 'treesit-auto-recipe-list
               (make-treesit-auto-recipe
                :lang 'prisma
                :ts-mode 'prisma-ts-mode
                :remap '(prisma-mode)
                :url "https://github.com/victorhqc/tree-sitter-prisma"
                :revision "master"
                :source-dir "src"
                :ext "\\.prisma\\'"))

  (add-to-list 'treesit-auto-recipe-list
               (make-treesit-auto-recipe
                :lang 'svelte
                :ts-mode 'svelte-ts-mode
                :remap 'svelte-mode
                :url "https://github.com/Himujjal/tree-sitter-svelte"
                :source-dir "./src"
                :ext "\\.svelte\\'"))

  (treesit-auto-add-to-auto-mode-alist 'all)
  (global-treesit-auto-mode)

  ;; add lambda function hook to list of emacs hooks
  (dolist (mode (my/get-treesit-auto-modes))
    (let* ((mode-name (symbol-name mode))
           (hook-name (concat mode-name "-hook")))
      (add-hook (intern hook-name) #'my/bring-previous-mode-hooks))))

Treesit fold

(use-package treesit-fold
  :ensure (treesit-fold :fetcher github :repo "emacs-tree-sitter/treesit-fold"))

Project Tasks

(use-package project-tasks
  :after project
  :defer t
  :commands (project-tasks)
  :init
  ;; Show project-tasks when switching projects
  (add-to-list 'project-switch-commands '(project-tasks "tasks") t)
  ;; Add action to embark-file map
  (with-eval-after-load 'embark
    (define-key embark-file-map (kbd "P") #'project-tasks))

  :custom
  (project-tasks-files '("tasks.org"))
  (project-tasks-separator " => ")
  :config
  (add-to-list 'marginalia-prompt-categories '("Select task" . project-task))
  (defvar-keymap embark-project-task-actions
    :doc "Keymap for actions for project-task (when mentioned by name)."
    :parent embark-general-map
    "j" #'project-tasks-goto-task)
  (add-to-list 'embark-keymap-alist '(project-task . embark-project-task-actions))
  ;; Bind project-tasks to project keymap
  :bind
  (:map project-prefix-map ("P" . project-tasks)))

Scratch (link)

Scratch is an extension to Emacs that enables one to create scratch buffers that are in the same mode as the current buffer. This is notably useful when working on code in some language; you may grab code into a scratch buffer, and, by virtue of this extension, do so using the Emacs formatting rules for that language.

(use-package scratch)

diff-hl

(use-package diff-hl
  :commands global-diff-hl-mode
  :hook
  ((magit-pre-refresh . diff-hl-magit-pre-refresh)
   (magit-post-refresh . diff-hl-magit-post-refresh)
   (dired-mode . diff-hl-dired-mode))
  :config
  (global-diff-hl-mode))

Editor Config (link)

EditorConfig helps maintain consistent coding styles for multiple developers working on the same project across various editors and IDEs. The EditorConfig project consists of a file format for defining coding styles and a collection of text editor plugins that enable editors to read the file format and adhere to defined styles. EditorConfig files are easily readable and they work nicely with version control systems.

(use-package editorconfig
  :init
  (editorconfig-mode 1))

goggles (link)

(use-package goggles
  :hook ((prog-mode text-mode) . goggles-mode)
  :custom
  (goggles-pulse t))

launchctl

(use-package launchctl)

Matching Paren Overlay

(use-package matching-paren-overlay
  :ensure
  (matching-paren-overlay
   :fetcher git
   :url "https://codeberg.org/acdw/matching-paren-overlay.el.git")
  :config
  (matching-paren-overlay-mode))

Treemacs

(use-package treemacs
  :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))
  :config
  (treemacs-follow-mode t)
  (treemacs-filewatch-mode t)
  (treemacs-fringe-indicator-mode 'always))

(use-package treemacs-projectile
  :after (treemacs projectile)
  :ensure t)

(use-package treemacs-nerd-icons
  :after treemacs
  :config
  (treemacs-load-theme "nerd-icons"))

Projectile (link)

Projectile is a project interaction library for Emacs. Its goal is to provide a nice set of features operating on a project level without introducing external dependencies (when feasible)

(use-package projectile
  :demand t
  :bind-keymap
  ("C-c p" . projectile-command-map)
  :custom
  (projectile-enable-caching nil)
  (projectile-sort-order 'recently-active)
  (projectile-project-search-path '("~/Developer/"))
  (projectile-ignored-projects `("~/"
                                 "/opt/homebrew"
                                 "/tmp/"
                                 "/private/tmp/"
                                 "~/Developer/work"
                                 ,package-user-dir))
  (projectile-track-known-projects-automatically nil)
  :config
  (projectile-mode)
  ;; Projectile is testing in the reverse order so more specific must me at the end

  (projectile-register-project-type
   'npm '("package.json")
   :compile "npm i"
   :test "npm test"
   :run "npm start"
   :test-suffix ".spec.js")

  (projectile-register-project-type
   'opera
   '("desktop/BUILD.gn" "desktop/gn_opera.py")
   :project-file "desktop/BUILD.gn"
   :run (concat "open $HOME/Developer/work/chromium/src/out/Release/Opera.app --args"
                " --allow-running-insecure-content"
                " --disable-web-security"
                " --ignore-certificate-errors"
                " --remote-debugging-port=9222"
                " --sticky-site-url-override=https://gxcorner.games"
                " --user-data-dir=$HOME/Developer/clean-profile/$(date +\"%Y-%m-%dT%H:%M:%S\")"
                " --use-mock-keychain")
   :configure "$HOME/goma/goma_ctl.py ensure_start && desktop/gn_opera.py --release product=\\\"gx\\\" use_jumbo_build=false use_remoteexec=true goma_dir=\"\\\"/Users/opera_user/goma\\\"\""
   :compile "autoninja -C chromium/src/out/Release opera"))

ibuffer-projectile (link)

(use-package ibuffer-projectile
  :hook
  (ibuffer . (lambda ()
               (ibuffer-projectile-set-filter-groups)
               (unless (eq ibuffer-sorting-mode 'alphabetic)
                 (ibuffer-do-sort-by-alphabetic)))))

Embark (link)

(defun embark-which-key-indicator ()
  "An embark indicator that displays keymaps using which-key.
The which-key help message will show the type and value of the
current target followed by an ellipsis if there are further
targets."
  (lambda (&optional keymap targets prefix)
    (if (null keymap)
        (which-key--hide-popup-ignore-command)
      (which-key--show-keymap
       (if (eq (plist-get (car targets) :type) 'embark-become)
           "Become"
         (format "Act on %s '%s'%s"
                 (plist-get (car targets) :type)
                 (embark--truncate-target (plist-get (car targets) :target))
                 (if (cdr targets) "" "")))
       (if prefix
           (pcase (lookup-key keymap prefix 'accept-default)
             ((and (pred keymapp) km) km)
             (_ (key-binding prefix 'accept-default)))
         keymap)
       nil nil t (lambda (binding)
                   (not (string-suffix-p "-argument" (cdr binding))))))))

(defun embark-hide-which-key-indicator (fn &rest args)
  "Hide the which-key indicator immediately when using the completing-read prompter."
  (which-key--hide-popup-ignore-command)
  (let ((embark-indicators
         (remq #'embark-which-key-indicator embark-indicators)))
    (apply fn args)))

(advice-add #'embark-completing-read-prompter
            :around #'embark-hide-which-key-indicator)

(use-package embark
  :after which-key
  :demand t
  :bind
  (("s-." . embark-act)         ;; pick some comfortable binding
   ("C-h b" . embark-bindings)) ;; alternative for `describe-bindings'

  :custom
  (embark-indicators
   '(embark-which-key-indicator
     embark-highlight-indicator
     embark-isearch-highlight-indicator))

  (prefix-help-command #'embark-prefix-help-command)

  :config
  ;; Unbind help-command so completing-read interface can do it's job
  (unbind-key "C-h <help>" global-map)
  (unbind-key "C-h" help-map)
  ;;(unbind-key "C-h" ehelp-map)

  ;; Hide the mode line of the Embark live/completions buffers
  (add-to-list 'display-buffer-alist
               '("\\`\\*Embark Collect \\(Live\\|Completions\\)\\*"
                 nil
                 (window-parameters (mode-line-format . none)))))

highlight-global

(use-package highlight-global
  :ensure (highlight-global :fetcher github :repo "kaushalmodi/highlight-global")
  :bind
  ("C-s-h" . highlight-global-hl-frame-toggle))

Embark Consult (link)

Consult users will also want the embark-consult package.

(use-package embark-consult
  :after (embark consult)
  :demand t
  :hook
  (embark-collect-mode . consult-preview-at-point-mode))

Corfu (link)

(use-package corfu
  :defer 1
  :after orderless

  :preface
  (defun corfu-enable-always-in-minibuffer ()
    "Enable Corfu in the minibuffer if Vertico/Mct are not active."
    (unless (or (bound-and-true-p mct--active) ; Useful if I ever use MCT
                (bound-and-true-p vertico--input))
      (setq-local corfu-auto nil) ; Ensure auto completion is disabled
      (corfu-mode 1)))

  :hook (minibuffer-setup . corfu-enable-always-in-minibuffer)
  :bind (:map corfu-map
              ("C-n" . corfu-next)
              ("C-p" . corfu-previous)
              ("<escape>" . corfu-quit)
              ("<return>" . corfu-insert)
              ("M-d" . corfu-popupinfo-show)
              ("M-l" . corfu-show-location)
              ("H-SPC" . corfu-insert-separator)
              ("SPC" . corfu-insert-separator))

  :custom
  (completion-cycle-threshold nil)
  (corfu-auto t)
  (corfu-auto-delay 0)
  (corfu-auto-prefix 1)
  (corfu-count 14)
  (corfu-cycle t)
  (corfu-echo-documentation t)
  (corfu-min-width 80)
  (corfu-max-width corfu-min-width)
  (corfu-preselect-first t)
  (corfu-preview-current t)
  (corfu-preselect 'prompt)
  (corfu-separator ?\s)
  (corfu-quit-at-boundary :separator)
  (corfu-quit-no-match t)
  (corfu-scroll-margin 4)
  (corfu-popupinfo-delay '(0.3 . 0.1))
  (corfu-popupinfo-hide nil)
  (tab-always-indent 'complete)
  (tab-first-completion 'word-or-paren-or-punct)
  (read-extended-command-predicate #'command-completion-default-include-p)

  :config
  (global-corfu-mode 1)
  (corfu-history-mode 1)
  (corfu-popupinfo-mode 1))

;; Use dabbrev with Corfu!
(use-package dabbrev
  :ensure nil
  ;; Swap M-/ and C-M-/
  :bind (("M-/" . dabbrev-completion)
         ("C-M-/" . dabbrev-expand))
  :config
  (add-to-list 'dabbrev-ignored-buffer-regexps "\\` ")
  (add-to-list 'dabbrev-ignored-buffer-modes 'doc-view-mode)
  (add-to-list 'dabbrev-ignored-buffer-modes 'tags-table-mode))

Cape (link)

(use-package cape
  :bind (("C-." . completion-at-point)
         ("C-c /" . cape-dabbrev))
  :init
  (add-to-list 'completion-at-point-functions #'cape-file))

Org

org-mode (link)

Org mode is for keeping notes, maintaining TODO lists, planning projects, and authoring documents with a fast and effective plain-text syste.

(defmacro org-babel-add-langs (langs)
  `(org-babel-do-load-languages
    'org-babel-load-languages
    (append org-babel-load-languages
            ',langs)))

(defun alist-unique (alist)
  (reduce (lambda (output value)
            (let* ((key (car value))
                   (existing-value (alist-get key output)))
              (cond ((not output) (list value))
                    ((not existing-value) (append output (list value)))
                    (t output))))
          alist :initial-value nil))

(defun append-alist-unique (values alist)
  "Add unique VALUE to ALIST when car of VALUE is unique, returns ALIST otherwise"
  (alist-unique (append alist values)))

(use-package org
  :ensure nil
  :mode (("\\.org$" . org-mode))
  :hook
  (org-mode . turn-on-auto-fill)
  :bind
  ("C-c l" . org-store-link)
  ("C-c a" . org-agenda)
  ("C-c c" . org-capture)

  :config
  (org-babel-add-langs ((emacs-lisp .  t)))
  (org-indent-mode 1)
  (custom-set-faces '(org-ellipsis ((t (:foreground "gray40" :underline nil)))))
  (org-babel-add-langs
   ((ditaa . t)))
  :custom
  (org-src-window-setup 'current-window)
  (org-modules
   '(org-protocol
     org-habit
     org-mouse
     org-tempo))
  (org-blank-before-new-entry
   '((heading . t)
     (plain-list-item . nil)))
  (org-confirm-babel-evaluate
   (lambda (lang body)
     (not (string= lang "restclient"))))
  (org-hide-leading-stars t)
  (org-src-tab-acts-natively t)
  (org-startup-indented t)
  (org-startup-folded "content")
  (org-startup-with-inline-images t)
  (org-babel-min-lines-for-block-output 1)
  (org-speed-command-help t)
  (org-src-preserve-indentation t)
  (org-ellipsis "" )
  (org-pretty-entities t)
  (org-hide-emphasis-markers t)
  (org-agenda-block-separator "")
  (org-fontify-whole-heading-line nil)
  (org-fontify-done-headline t)
  (org-fontify-quote-and-verse-blocks t)
  (org-tags-column 0)
  (org-indent-indentation-per-level 0)
  (org-directory "~/Dropbox/org")
  (org-default-notes-file "notes.org")
  (org-refile-targets '((org-agenda-files :maxlevel . 1)))
  (org-refile-allow-creating-parent-nodes 'confirm)
  (org-auto-align-tags nil)
  (org-catch-invisible-edits 'show-and-error)
  (org-special-ctrl-a/e t)
  (org-insert-heading-respect-content t)
  (org-agenda-tags-column 0)
  (org-agenda-block-separator ?─)
  (org-agenda-time-grid
   '((daily today require-timed)
     (800 1000 1200 1400 1600 1800 2000))
   " ┄┄┄┄┄ " "┄┄┄┄┄┄┄┄┄┄┄┄┄┄┄")
  (org-agenda-current-time-string "◀── now ─────────────────────────────────────────────────")

  (org-capture-templates
   '(("a" "Appointment" entry (file  "gcal.org" )
      "* %?\n\n%^T\n\n:PROPERTIES:\n\n:END:\n\n")
     ("l" "Link" entry (file+headline "links.org" "Links")
      "* %? %^L %^g \n%T" :prepend t)
     ("b" "Blog idea" entry (file+headline "todo.org" "Blog Topics:")
      "* %?\n%T" :prepend t)
     ("t" "Todo Item" entry
      (file+headline "todo.org" "Todo")
      "* TODO %?\n:PROPERTIES:\n:CREATED: %u\n:END:" :prepend t :empty-lines 1)
     ("n" "Note" entry (file+headline "todo.org" "Note space")
      "* %?\n%u" :prepend t)
     ("j" "Journal" entry (file+olp+datetree "journal.org")
      "* %?\nEntered on %U\n  %i\n  %a")
     )))
(use-package org-habit
  :ensure nil)

(use-package org-starless
  :hook (org-mode . org-starless-mode)
  :ensure (org-starless :fetcher github :repo "TonCherAmi/org-starless"))

(use-package org-tree-slide
  :custom
  (org-tree-slide-skip-outline-level 4)
  (org-tree-slide-skip-done nil)
  :bind
  ("<f8>" . org-tree-slide-mode)
  ("S-<f8>" . org-tree-slide-skip-done-toggle)
  (:map org-tree-slide-mode-map
        ("<f9>" . org-tree-slide-move-previous-tree)
        ("<f10>" . org-tree-slide-move-next-tree)
        ("<f11>" . org-tree-slide-content))
  :config
  (org-tree-slide-narrowing-control-profile))

;; org-babel
(org-babel-add-langs
 ((emacs-lisp . t)
  (shell . t)))

(use-package ob-restclient
  :defer 2
  :custom
  (org-babel-default-header-args:restclient
   '((:results . "raw")
     (:async . "yes")))
  :config
  (org-babel-add-langs
   ((restclient . t))))

(use-package ob-js
  :ensure nil
  :commands (org-mode)
  :config
  (org-babel-add-langs
   ((js . t)))

  (add-to-list 'org-babel-tangle-lang-exts '("js" . "js")))

(use-package ob-deno
  :defer 2
  :config
  (org-babel-add-langs
   ((deno . t))))

(use-package ob-mermaid
  :ensure-system-package (mmdc . "npm install -g @mermaid-js/mermaid-cli")
  :config
  (org-babel-add-langs
   ((mermaid . t))))

(use-package ob-async)

(use-package org-super-agenda
  :defer 2
  :custom
  (org-super-agenda-groups
   ;; Each group has an implicit boolean OR operator between its selectors.
   '((:name "Today"        ; Optionally specify section name
            :time-grid t   ; Items that appear on the time grid
            :todo "TODAY") ; Items that have this TODO keyword
     (:name "Important"
            ;; Single arguments given alone
            :tag "bills"
            :priority "A")
     ;; Set order of multiple groups at once
     (:order-multi (2 (:name "Shopping in town"
                             ;; Boolean AND group matches items that match all subgroups
                             :and (:tag "shopping" :tag "@town"))
                      (:name "Food-related"
                             ;; Multiple args given in list with implicit OR
                             :tag ("food" "dinner"))
                      (:name "Personal"
                             :habit t
                             :tag "personal")
                      (:name "Space-related (non-moon-or-planet-related)"
                             ;; Regexps match case-insensitively on the entire entry
                             :and (:regexp ("space" "NASA")
                                           ;; Boolean NOT also has implicit OR between selectors
                                           :not (:regexp "moon" :tag "planet")))))
     ;; Groups supply their own section names when none are given
     (:todo "WAITING" :order 8)  ; Set order of this section
     (:todo ("SOMEDAY" "TO-READ" "CHECK" "TO-WATCH" "WATCHING")
            ;; Show this group at the end of the agenda (since it has the
            ;; highest number). If you specified this group last, items
            ;; with these todo keywords that e.g. have priority A would be
            ;; displayed in that group instead, because items are grouped
            ;; out in the order the groups are listed.
            :order 9)
     (:priority<= "B"
                  ;; Show this section after "Today" and "Important", because
                  ;; their order is unspecified, defaulting to 0. Sections
                  ;; are displayed lowest-number-first.
                  :order 1)
     ;; After the last group, the agenda will display items that didn't
     ;; match any of these groups, with the default order position of 99
     ))
  (org-super-agenda-mode 1))

(defun make-orgcapture-frame ()
  "Create a new frame and run org-capture."
  (interactive)
  (make-frame '((name . "remember") (width . 80) (height . 16)
                (top . 400) (left . 300)
                ;; (font . "-apple-Monaco-medium-normal-normal-*-13-*-*-*-m-0-iso10646-1")
                ))
  (select-frame-by-name "remember")
  (org-capture)
  (delete-other-windows))

(use-package yequake
  :custom
  (yequake-frames
   '(("org-capture"
      (buffer-fns . (yequake-org-capture))
      (width . 0.75)
      (height . 0.5)
      (alpha . 0.95)
      (frame-parameters . ((undecorated . t)
                           (skip-taskbar . t)
                           (sticky . t)))))))

Org Roam

(defun org-roam-node-insert-immediate (arg &rest args)
  "This will allow you to quickly create new notes for topics
you're mentioning while writing so that you can go back later and
fill those notes in with more details!"
  (interactive "P")
  (let ((args (cons arg args))
        (org-roam-capture-templates (list (append (car org-roam-capture-templates)
                                                  '(:immediate-finish t)))))
    (apply #'org-roam-node-insert args)))

(defun my/org-roam-filter-by-tag (tag-name)
  "returns a filter function for "
  (lambda (node)
    (member tag-name (org-roam-node-tags node))))

(defun my/org-roam-list-notes-by-tag (tag-name)
  "Returns list of noted with given filetag"
  (mapcar #'org-roam-node-file
          (seq-filter
           (my/org-roam-filter-by-tag tag-name)
           (org-roam-node-list))))

(defun my/org-roam-refresh-agenda-list ()
  "Refreshes the agenda list adding Project notes to the list"
  (interactive)
  (setq org-agenda-files
        (append org-agenda-files
                (my/org-roam-list-notes-by-tag "Project")
                (my/org-roam-list-notes-by-tag "Plant"))))

(defun my/org-roam-template-dir-expand (file)
  (expand-file-name (concat user-emacs-directory file)))

(use-package org-roam
  :after org
  :custom
  (org-roam-node-display-template (concat "${title:*} " (propertize "${tags:10}" 'face 'org-tag)))
  (org-roam-directory "~/Dropbox/OrgRoam")
  (org-roam-completion-everywhere nil)
  :bind (("C-c n l" . org-roam-buffer-toggle)
         ("C-c n f" . org-roam-node-find)
         ("C-c n g" . org-roam-graph)
         ("C-c n i" . org-roam-node-insert)
         ("C-c n c" . org-roam-capture)
         ("C-c n I" . org-roam-node-insert-immediate)
         ;; Dailies
         ("C-c n j" . org-roam-dailies-capture-today)

         :map org-mode-map
         ("C-M-i"    . completion-at-point)

         :map org-roam-dailies-map
         ("Y" . org-roam-dailies-capture-yesterday)
         ("T" . org-roam-dailies-capture-tomorrow))

  :bind-keymap
  ("C-c n d" . org-roam-dailies-map)
  :custom-face
  (org-roam-link ((t (:foreground "#e24888" :underline t))))
  (org-roam-link-current ((t (:foreground "#e24888" :underline t))))
  :config
  (org-roam-setup)
  (require 'org-roam-dailies)
  (org-roam-db-autosync-mode)
  (my/org-roam-refresh-agenda-list)
  (setq org-roam-capture-templates
        `(("d" "default" plain
           "%?"
           :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n")
           :unnarrowed t)
          ("e" "elisp" plain
           (file ,(my/org-roam-template-dir-expand "etc/org-roam/templates/elisp.org"))
           :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n#+category: ${title}\n#+filetags: elisp\n")
           :unnarrowed t)
          ("p" "project" plain
           (file ,(my/org-roam-template-dir-expand "etc/org-roam/templates/project.org"))
           :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n#+category: ${title}\n#+filetags: Project\n")
           :unnarrowed t)
          ("r" "proposal" plain
           (file ,(my/org-roam-template-dir-expand "etc/org-roam/templates/proposal.org"))
           :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n#+category: ${title}\n#+filetags: Proposal\n")
           :unnarrowed t)
          ("f" "food" plain
           (file ,(my/org-roam-template-dir-expand "etc/org-roam/templates/food.org"))
           :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n#+category: ${title}\n#+filetags: Food\n")
           :unnarrowed t)
          ("t" "plant" plain
           (file ,(my/org-roam-template-dir-expand "etc/org-roam/templates/plant.org"))
           :if-new (file+head "%<%Y%m%d%H%M%S>-${slug}.org" "#+title: ${title}\n#+date: %U\n#+category: ${title}\n#+filetags: Plant\n")
           :unnarrowed t))))

Htmlize for org-mode

(use-package htmlize)

org-cliplink (link)

(use-package org-cliplink
  :bind ("C-x p i" . org-cliplink))

org-roam-ui

(use-package org-roam-ui
  :ensure (:host github :repo "org-roam/org-roam-ui" :branch "main" :files ("*.el" "out"))
  :defer 2
  :after (org-roam websocket)
  ;;         if you don't care about startup time, use
  :custom
  (org-roam-ui-sync-theme t)
  (org-roam-ui-follow t)
  (org-roam-ui-update-on-save t)
  (org-roam-ui-open-on-start t)
  :config
  (org-roam-ui-mode 1))

Org Tidy

(use-package org-tidy
  :hook
  (org-mode . org-tidy-mode))

Org Download

(use-package org-download
  :hook ((dired-mode org-mode) . org-download-enable)
  :ensure-system-package pngpaste
  :custom
  (org-download-screenshot-method "screencapture -i %s"))

Better help dialogs

(use-package helpful
  :bind (("C-h f"  . helpful-callable)
         ("C-h v"  . helpful-variable)
         ("C-h k"  . helpful-key)
         ("C-c C-d" . helpful-at-point)
         ("C-h k"  . helpful-key)))

pnpm-mode

(use-package pnpm-mode
  :custom
  (pnpm-mode-command-prefix "C-c s-n"))

Open dash at point

(use-package dash-at-point
  :bind
  ("C-c d" . dash-at-point)
  ("C-c e" . dash-at-point-with-docset))

Anzu - current match / all matches in modeline

(use-package anzu
  :init
  (global-anzu-mode +1)
  :bind
  ("M-%" . anzu-query-replace)
  ("C-M-%" . anzu-query-replace-regexp))

Modeline

Doom Modeline

(use-package doom-modeline
  :custom-face
  (doom-modeline-bar ((t (:inherit default))))
  :custom
  (doom-modeline-hud t)
  (doom-modeline-icon t)
  ;; hack
  (doom-modeline-bar-width 1)
  (doom-modeline-major-mode-icon t)
  (doom-modeline-major-mode-color-icon t)
  (doom-modeline-buffer-state-icon t)
  (doom-modeline-buffer-modification-icon t)
  (doom-modeline-minor-modes nil)
  (doom-modeline-github nil)
  (doom-modeline-checker-simple-format nil)
  (doom-modeline-height 30)
  :config
  (doom-modeline-mode))

Hide Modeline

Hides modeline whenever this minor mode is active

(use-package hide-mode-line
  :commands hide-mode-line-mode)

Git

magit - best git client ever

(use-package magit
  :after transient
  :bind ("C-x g" . magit-status)
  :hook
  (git-commit-mode . flyspell-mode)
  :custom
  (vc-handled-backends nil)
  (magit-process-finish-apply-ansi-colors t)
  (magit-refresh-status-buffer t)
  (magit-display-buffer-function 'magit-display-buffer-same-window-except-diff-v1)
  (magit-bury-buffer-function 'magit-restore-window-configuration)
  (magit-process-password-functions '(magit-process-password-auth-source))

  ;; optimisation
  (magit-diff-highlight-indentation nil)
  (magit-diff-highlight-trailing nil)
  (magit-diff-paint-whitespace nil)
  
  :config
  (remove-hook 'magit-refs-sections-hook 'magit-insert-tags)
  ;; TODO: add to magit-process-password-functions an auth source
  (transient-define-suffix magit-submodule-update-all ()
    "Update all submodules"
    :description "Update All (git submodule update --init --recursive)"
    (interactive)
    (magit-with-toplevel
      (magit-run-git-async "submodule" "update" "--init" "--recursive"))))
(use-package forge
  :after magit
  :config
  (add-to-list 'forge-alist '("gitlab.services.ams.osa" "gitlab.services.ams.osa/api/v4" "gitlab.services.ams.osa" forge-gitlab-repository))
  (add-to-list 'forge-alist '("gitlab.service.osa" "gitlab.service.osa/api/v4" "gitlab.service.osa" forge-gitlab-repository)))

Conventional Commit

(use-package conventional-commit
  :ensure (conventional-commit :fetcher github :repo "akirak/conventional-commit.el")
  :hook
  (git-commit-mode . conventional-commit-setup))

browse-at-remote (link)

(use-package browse-at-remote
  :bind ("C-c C-g" . browse-at-remote)
  :custom
  (browse-at-remote-remote-type-regexps
   '(
     (:host "^git\\.service\\.osa"               :type "oslo")
     (:host "^gitlab\\.services\\.ams\\.osa$" :type "gitlab")
     (:host "^gitlab\\.service\\.osa$"        :type "gitlab")
     (:host "^github\\.com$"                  :type "github")
     (:host "^bitbucket\\.org$"               :type "bitbucket")
     (:host "^gitlab\\.com$"                  :type "gitlab")
     (:host "^gist\\.github\\.com$"           :type "gist"))))

(defun browse-at-remote-oslo-format-url (repo-url)
  "Get a gnu formatted URL."
  (let* ((parts (split-string repo-url "/var/git" t))
   (domain (butlast parts))
   (project (car (last parts))))
    (string-join
     (append domain (list project)) "/")))

(defun browse-at-remote--format-region-url-as-oslo (repo-url location filename &optional linestart lineend)
  "URL formatter for gnu."
  (let ((repo-url (browse-at-remote-oslo-format-url repo-url)))
    (cond
     (linestart (format "%s/tree/%s?h=%s#n%d" repo-url filename location linestart))
     (t (format "%s/tree/%s?h=%s" repo-url filename location)))))

(defun browse-at-remote--format-commit-url-as-gnu (repo-url commithash)
  "Commit URL formatted for gnu"
  (format "%s/commit/?id=%s" (browse-at-remote-oslo-format-url repo-url) commithash))

gitlab-pipeline

(use-package gitlab-pipeline
  :custom
  (gitlab-pipeline-host "gitlab.services.ams.osa/api/v4"))

docker

(use-package docker
  :ensure t
  :bind ("C-c d" . docker))

hl-todo-mode (link)

(use-package hl-todo
  :config
  :hook (prog-mode . hl-todo-mode))

goto-line-preview

(use-package goto-line-preview
  :bind ([remap goto-line] . goto-line-preview)
  :config)

pulsar

(use-package pulsar
  :config
  (pulsar-global-mode 1))

Snippets

(use-package yasnippet
  :after lsp-mode
  :hook (prog-mode . yas-minor-mode))

(use-package yasnippet-snippets
  :after yasnippet
  :config
  (yas-reload-all))

keyfreq

(use-package keyfreq
  :custom
  (keyfreq-excluded-commands
   (list ignore
         mwheel-scroll
         self-insert-command
         forward-char
         left-char
         right-char
         backward-char
         previous-line
         next-line))
  :config
  (keyfreq-mode 1)
  (keyfreq-autosave-mode 1))

rg

ripgrep frontend

(use-package rg
  :ensure-system-package (rg . ripgrep)
  :bind
  ("C-c s" . rg-menu)
  :custom
  (rg-custom-type-aliases
   '(("svelte" .    "*.svelte")
     ("ts"     .    "*.tsx?")
     ("env"    .    "\.env.*"))))

Dired

I’ve tried ~ranger-mode~ with it’s simplier ~deer-mode~ and I must say, nothing beets good old Dired.

With some additions of course, like ~diredfl~ for colors and ~dired-quick-sort~ for better sorting with native gnu ls

(use-package dired
  :ensure nil
  :defer 0.5
  :custom
  (dired-dwim-target t)
  (dired-vc-rename-file t)
  (dired-auto-revert-buffer t)
  :config
  (cond ((string-equal system-type "darwin")
         (setq insert-directory-program "gls"
               dired-use-ls-dired t)
         (setq dired-listing-switches "-agho --group-directories-first"))))

(use-package dired-quick-sort
  :after dired
  :custom
  (ls-lisp-use-insert-directory-program t)
  :config
  (dired-quick-sort-setup))

(use-package dired-subtree
  :after dired
  :bind (:map dired-mode-map
              ("TAB" . dired-subtree-toggle)))

Emacs Everywhere

(use-package emacs-everywhere
  :defer 1
  :custom
  (emacs-everywhere-frame-parameters '((name . "emacs-everywhere") (fullscreen) (width . 160) (height . 24)))
  (emacs-everywhere-clipboard-sleep-delay 0.005)
  :config

  (defun emacs-everywhere--ensure-oscascript-compiled (&optional force)
    "Ensure that compiled oscascript files are present.
Will always compile when FORCE is non-nil."
    (unless (and (file-exists-p "app-name")
                 (file-exists-p "window-geometry")
                 (file-exists-p "window-title")
                 (not force))
      (let ((default-directory emacs-everywhere--dir)
            (app-name
             "tell application \"System Events\"
    set frontAppName to name of first application process whose frontmost is true
end tell
return frontAppName")
            (window-geometry
             "tell application \"System Events\"
     set frontWindow to front window of (first application process whose frontmost is true)
     set windowPosition to (get position of frontWindow)
     set windowSize to (get size of frontWindow)
end tell
return windowPosition & windowSize")
            (window-title
             "set windowTitle to \"\"
tell application \"System Events\"
     set frontAppProcess to first application process whose frontmost is true
end tell
tell frontAppProcess
    if count of windows > 0 then
        set windowTitle to name of front window
    end if
end tell
return windowTitle"))
        (dolist (script `(("app-name" . ,app-name)
                          ("window-geometry" . ,window-geometry)
                          ("window-title" . ,window-title)))
          (write-region (cdr script) nil (concat (car script) ".applescript"))
          (shell-command (format "osacompile -t osas -o %s %s"
                                 (car script) (concat (car script) ".applescript"))))))))

monkeytype

(use-package monkeytype
  :hook (monkeytype . centered-cursor-mode))

centered-cursor-mode

(use-package centered-cursor-mode)

Prog modes

bash

(use-package bash-mode
  :ensure nil
  :hook (bash-mode . lsp-deferred))

prisma

(use-package prisma-mode
  :mode ("\\.prisma\\'" . prisma-mode)
  :ensure (prisma-mode :fetcher github :repo "pimeys/emacs-prisma-mode" :branch "main")
  :hook (prisma-mode . lsp-deferred))

el

(use-package emacs-lisp
  :ensure nil
  :bind
  ((:map global-map
         ("C-x C-e" . nil))
   (:map emacs-lisp-mode-map
         ("C-x C-e" . eval-last-sexp))))

rust

(use-package rust-mode
  :defer 0.5
  :custom
  (rust-mode-treesitter-derive t)
  :config
  (setq auto-mode-alist (assoc-delete-all "\\.rs\\'" auto-mode-alist)))

rustic

(use-package rustic
  :after (rust-mode)
  :mode ("\\.rs\\'" . rustic-mode)
  :preface
  (defun rustic-mode-auto-save-hook ()
    "Enable auto-saving in rustic-mode buffers."
    (when buffer-file-name
      (setq-local compilation-ask-about-save nil)))
  :hook
  (rustic-mode-hook . rustic-mode-auto-save-hook))

.env

(use-package dotenv-mode
  :mode ("\\.env\\..*\\'" . dotenv-mode))

Elisp

(use-package elisp
  :ensure nil
  :mode ("\\.el\\'" . emacs-lisp-mode))
(use-package highlight-defined
  :hook
  (emacs-lisp-mode . highlight-defined-mode))

Markdown

(use-package markdown-ts-mode
  :mode ("\\.md\\'" . markdown-ts-mode)
  :defer 't
  :config
  (add-to-list 'treesit-language-source-alist '(markdown "https://github.com/tree-sitter-grammars/tree-sitter-markdown" "split_parser" "tree-sitter-markdown/src"))
  (add-to-list 'treesit-language-source-alist '(markdown-inline "https://github.com/tree-sitter-grammars/tree-sitter-markdown" "split_parser" "tree-sitter-markdown-inline/src")))

(use-package grip-mode
  :bind
  (:map markdown-mode-command-map
        ("g" . grip-mode))
  :config
  (let ((credential (auth-source-user-and-password "github.com")))
    (setq grip-github-user (car credential)
          grip-github-password (cadr credential))))

(use-package edit-indirect
  :after markdown-mode)

YAML

(use-package yaml-mode
  :mode "\\.yaml")

GO

(use-package go-mode
  :mode "\\.go"
  :config
  (add-hook 'go-mode-hook
            (lambda ()
              (add-hook 'before-save-hook 'gofmt-before-save)
              (local-set-key (kbd "M-.") 'godef-jump))))

JSON

(use-package json-mode
  :mode "\\.json$"
  :hook
  (json-mode . lsp-deferred)
  :interpreter "json"
  :config
  (setq js-indent-level 2))

CSS

(use-package css-mode
  :ensure nil
  :mode "\\.css")

SCSS

(use-package scss-mode
  :mode "\\.scss"
  :hook (scss-mode . lsp-deferred))

LUA

(use-package lua-mode
  :mode ("\\.lua"))

JS

(use-package typescript-mode
  :after (lsp-mode)
  :mode "\\.ts$"
  :hook (typescript-mode . lsp-deferred))

(use-package js2-mode
  :after (lsp-mode)
  :mode ("\\.[cm]*js$")
  :hook (js-base-mode . lsp-deferred))

(use-package eslintd-fix
  :hook ((js-base-mode) . eslintd-fix-mode))

(use-package web-mode
  :mode
  ("\\.html\\'")
  :hook
  (web-mode . lsp-deferred)
  :custom
  (web-mode-content-types-alist
   '(("jsx" . "\\.tsx\\'")
     ("jsx" . "\\.jsx\\'")
     ("html" . "\\.html\\'")))
  (web-mode-enable-auto-indentation nil)
  (web-mode-indentation-params
   '(("lineup-args" . t)
     ("lineup-calls" . t)
     ("lineup-concats" . t)
     ("lineup-quotes" . t)
     ("lineup-ternary" . nil)
     ("case-extra-offset" . t))))

Py

(use-package python-mode
  :mode "\\.py"
  :interpreter "py"
  :hook (python-mode . lsp-deferred)
  :config
  (setq python-shell-interpreter "ipython"
        python-shell-interpreter-args "-i --simple-prompt"))

(use-package poetry
  :after python-mode
  :config
  (poetry-tracking-mode))

Svelte

(use-package svelte-ts-mode
  :mode ("\\.svelte\\'")
  :ensure (:host github :repo "leafOfTree/svelte-ts-mode")
  :config
  (add-hook 'editorconfig-after-apply-functions
            (lambda (props)
              (let* ((indent (string-to-number (gethash 'indent_size props "0"))))
                (if (>= indent 0)
                  (setq-local svelte-ts-mode-indent-offset indent)
                  (setq-local css-indent-offset indent))))))

Dockerfile and docker-compose.yml

(use-package dockerfile-mode
  :mode "Dockerfile$")

(use-package docker-compose-mode
  :mode "docker-compose.yml.py$")

Debug Emacs

Explain Pause

(use-package explain-pause-mode
  :ensure (explain-pause-mode :fetcher github :repo "lastquestion/explain-pause-mode"))

Other

(message ".emacs loaded successfully.")